Scrape hotel reviews from Priceline: review text, pros/cons, reviewer info, and individual ratings. Get guest scores, category ratings, GPS coordinates, and neighborhood data for 107 cities or specific URLs. Export data, run via API, schedule runs, or integrate with other tools.
All notable changes to Priceline Hotel Reviews Scraper are documented here.
v0.5.4 (2026-06-02)
Changed (SEV-2 schema honesty — removed dead placeholder fields)
Removed 5 fields that were hardcoded null in the mapper and never present in the getHotelDetails response: chain, brand, propertyType, yearBuilt, yearRenovated. They promised data the API does not provide. (Hotel brand/type exist in Priceline's listings query, not details — a future coverage sprint could probe adding them.) ACTOR_VERSION/dataVersion → 0.5.4. Audit 2026-06-01 finding X-3.
v0.5.3 (2026-06-01)
Fixed (SEV-2 revenue leak — valid hotels were not charged)
Relaxed two over-strict zod constraints that marked complete hotels _incomplete (pushed but NOT charged): ratings.totalReviewCountmin(1)→min(0) (a new hotel with a complete profile and zero reviews is valid, chargeable data) and review overallRatingmin(1)→min(0) (a single review lacking an "overall" score entry — mapped to 0 — no longer fails the whole hotel). A 99-good-review hotel with one partial review was billing $0. Audit 2026-06-01 finding. ACTOR_VERSION/dataVersion bumped to 0.5.3.
v0.5.0 (2026-06-01)
Removed (BREAKING - SEV-3 audit)
roomTypes, nearbyPOIs, mandatoryFees fields dropped from output. These were declared in the HotelDetail type and always shipped as empty arrays ([] as never[]), advertised internally as "Phase 3+" deliverables that were never implemented. Rather than continue to expose placeholder columns, the fields are removed entirely. Each of them requires a separate GraphQL query against Priceline; if/when implemented, they will be added back behind a feature flag with real data.
Downstream consumers that referenced roomTypes, nearbyPOIs or mandatoryFees on output rows must update their parsers; the columns will no longer appear in JSON / CSV / Excel exports.
Changed
ACTOR_VERSION bumped to 0.5.0; actor.jsonversion: "0.5"; package.json synced. dataVersion on every output row now reads "0.5.0".
v0.4.5 (2026-06-01)
Fixed (SEV-4 review coverage)
Reviews pagination implemented. The actor previously fetched only the first page of reviews (max 100) regardless of maxReviewsPerHotel, and the documented value 0 (advertised as "all available reviews") returned 0 due to a guard inversion. Now: 0 means "fetch all up to a 1000-review safety cap"; any positive value loops through pages of 100 until the target is reached or totalPages is exhausted.
New reviewsTruncated: true flag on hotel rows where the actual reviews count is less than totalReviewCount (clear signal for downstream consumers that there are more reviews than fetched).
Cost impact: each additional review page = 1 ZenRows call. With Pullman Paris (2748 reviews), maxReviewsPerHotel=0 would issue ~10 ZenRows calls per hotel.
v0.4.4 (2026-05-31)
Fixed
reviews field now populates with individual guest reviews. The legacy hotelDetails.guestReviews field is permanently null in Priceline's API; the scraper now calls the dedicated getReviewsByHotelIds GraphQL operation (same endpoint, same proxy) that powers Priceline's "Show All Reviews" modal. Each review carries text, pros, cons, overallRating, reviewer.{name, location, travelerType}, reviewDate, and a server-side reviewId when provided.
Added
HOTEL_REVIEWS_QUERY constant in src/constants.ts — the reverse-engineered getReviewsByHotelIds operation (verbatim from assets.pclncdn.com/web/relax/.../RELAX.main.*.js).
fetchHotelReviews(proxy, hotelId, { limit, offset }) in src/priceline-api.ts — limit capped at 100 to avoid oversized responses; uses 1-indexed offsets (matches the bundle defaults).
mapReviewsV2(rawReviews) in src/parsers/graphql-mapper.ts — maps the new GraphQL response shape (scores[], reviewerInfo, entryDate) onto the existing HotelReview interface; preserves server-side reviewId and falls back to text-hash when absent.
Changed
main.ts reviews step decoupled from fetchHotelDetails: after profile mapping, it calls fetchHotelReviews (best-effort, never fails the hotel) and only when maxReviewsPerHotel > 0. PPE charging is unchanged: still a single Actor.pushData(hotel, 'hotel-extracted') per hotel.
Legacy mapReviews is retained for backwards compatibility but no longer called from main.ts.
ACTOR_VERSION bumped to 0.4.4; package.json + package-lock.json synced.
v0.4.3 (2026-05-29)
Added
amenities: array of structured amenity objects (code, name, type, free, displayable) mapped from hotelFeatures.hotelAmenities. Was previously hardcoded [].
amenitiesFlat: array of highlighted amenity codes mapped from hotelFeatures.highlightedAmenities. Was previously hardcoded [].
highlights: array of feature strings mapped from hotelFeatures.features (e.g., "Daily disinfection", "Family rooms"). Was previously hardcoded [].
photos: array of photo objects with thumbnail and full URLs mapped from hotel.images. Was previously hardcoded [].
policies: object with checkInTime, checkOutTime, petDescription, childrenDescription, importantInfo[] mapped from hotel.policies. Was previously hardcoded null.
Changed
Pure mapper enhancement: no changes to the GraphQL query (already requested these fields), the proxy client, or the schema validator (.passthrough() keeps backward compatibility). The fields were already arriving in the API response and were being silently dropped during mapping.
dataVersion bumped from 0.4.0 to 0.4.3 to reflect the enriched payload.
Known issues
reviews returns [] because Priceline's hotelDetails GraphQL endpoint now returns guestReviews: null. Recovering individual reviews requires reverse-engineering a separate reviews endpoint and is out of scope for this release.
Spending-limit log message no longer prints the raw chargedCount value. Apify SDK v3.7.2 doubles chargedCount when pushing to the default dataset with an explicit event (auto-schedules both hotel-extracted and synthetic apify-default-dataset-item), which made the log read chargedCount=2 and suggest double-billing. Only the explicit hotel-extracted event is billed by the Platform; the synthetic dataset event is local-only tracking. No revenue impact, only a cosmetic log fix.
v0.4.1 (2026-05-18)
Changed
Pricing section: fabricated "$49/month Scale plan" replaced with real "$29/month Starter plan" ($29 credits, ~5,800 hotels per month)
Terminology unified: "actor" replaced with "scraper" across body text, cross-promo table header ("Best actor" → "Best scraper"), REST API description, error-handling FAQ, and integrations heading
SEO title format aligned with portfolio (pipe separator)
Removed all em-dashes (zero em-dash policy 2026-05-18)
Removed etc. from scheduling FAQ
v0.4 (earlier)
Initial Store release. Pay-per-event pricing at $0.005 per hotel extracted. GraphQL-based extraction with city search, hotel URL, and hotel ID input modes.