HolidayCheck Reviews Scraper - German Hotel Ratings & Trends avatar

HolidayCheck Reviews Scraper - German Hotel Ratings & Trends

Pricing

from $0.80 / 1,000 review results

Go to Apify Store
HolidayCheck Reviews Scraper - German Hotel Ratings & Trends

HolidayCheck Reviews Scraper - German Hotel Ratings & Trends

Scrape German hotel reviews from HolidayCheck: guest reviews & ratings, verified-stay flags, hotel review sentiment by aspect, monthly trends, anomaly alerts and hotel reputation analytics for DACH hotels.

Pricing

from $0.80 / 1,000 review results

Rating

0.0

(0)

Developer

Kamer Ozkan

Kamer Ozkan

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 hours ago

Last modified

Categories

Share

HolidayCheck Reviews Scraper - Ratings, Aspects & Trends

Version 0.4.1 is a stateful, HTTP-first Apify Actor for collecting HolidayCheck hotel reviews and turning them into analytics-ready data, management reports, action alerts, health checks, and price-aware competitor intelligence.

This is an unofficial, independent Actor. It is not affiliated with, endorsed by, or supported by HolidayCheck.

The Actor is deployed privately on Apify, has passed controlled cloud runs, and has its pay-per-event launch pricing configured. Public Store activation remains gated by documentary confirmation of the lawful commercial basis, acceptance of the current Apify Store publishing terms by the account holder, and completion of the public listing identity assets.

What V4 includes

  • Multiple HolidayCheck hotels in one run
  • all, limit, and since collection modes
  • Page-by-page streaming through temporary Actor storage
  • A persistent checkpoint after every successful page
  • Optional cross-run deduplication by HolidayCheck review ID
  • Native ratings normalized to a 1-10 display scale
  • Eight deterministic aspect scores from HolidayCheck's native fields
  • Optional full-text AI aspect sentiment with exact source evidence
  • Native + AI hybrid aspect scores
  • Persistent monthly aspect trends and three-month rolling averages across scheduled runs
  • Observable anomaly signals, including writing patterns, near duplicates, rating runs, and historical burst z-scores
  • Optional full-text English translation
  • Shared AI request/token budgets and content-addressed caching
  • Automatic same-city-or-region and star-compatible competitor sets
  • Optional live comparable price bands using identical dates, occupancy, offer type, currency, and filters
  • Strict same-price-band selection when live price intelligence is enabled
  • English or German management reports in JSON, self-contained HTML, and plain text
  • Explainable decline, burst, duplicate-pattern, price-position, collection, and AI alerts
  • Optional signed HTTPS webhook delivery for email and messaging workflows
  • Machine-readable production health checks
  • Pay-per-event delivery gates for reviews, competitor sets, price intelligence, and reports
  • User spending-limit handling that turns finite review capacity into resumable collection work
  • Owner responses, optional raw contribution blocks, retries, proxy support, and per-hotel error isolation
  • Reviewer data minimization by default

Collection modes

collectionMode controls pagination:

  • all: ignores maxReviewsPerHotel and follows every publicly pageable result until the last or an empty page.
  • limit: returns at most maxReviewsPerHotel. The ending checkpoint remains incomplete, so a later run can continue at the next page.
  • since: requires cutoffDate and sort: "entrydate". It stops when the newest-first stream reaches an older review.

HolidayCheck can report a total review count larger than the number of reviews exposed through public pagination. all means every review that the current public interface actually makes pageable; the Actor does not claim access to private or non-indexed rows.

Each successfully processed page updates the named state store. Set:

  • resumeFromCheckpoint: true to continue an incomplete run.
  • deduplicateAcrossRuns: true to suppress IDs already emitted in earlier runs.
  • resetState: true to clear state for the input hotels before the run.
  • stateStoreName to isolate a customer, environment, or schedule.

When a limited run ends in the middle of a HolidayCheck page, the checkpoint deliberately revisits that page and skips only IDs already emitted. This prevents the remaining rows on that page from being silently lost.

Example input

{
"startUrls": [
{
"url": "https://www.holidaycheck.de/hr/bewertungen-pickalbatros-dana-beach-resort-hurghada/1aa4c4ad-f9ea-3367-a163-8a3a6884d450"
}
],
"collectionMode": "all",
"sort": "entrydate",
"resumeFromCheckpoint": true,
"deduplicateAcrossRuns": true,
"resetState": false,
"stateStoreName": "holidaycheck-review-intelligence-state",
"includeAspectScores": true,
"includeAiAspectScores": false,
"includeTrendIntelligence": true,
"includeAnomalySignals": true,
"includeReviewerDetails": false,
"includeOwnerResponses": true,
"includeCompetitorSet": true,
"competitorLimit": 5,
"competitorStarTolerance": 1,
"includePriceIntelligence": true,
"priceSearch": {
"checkIn": "2026-08-23",
"checkOut": "2026-08-30",
"adults": 2,
"childrenAges": [],
"rooms": 1,
"currency": "EUR",
"offerType": "package",
"departureAirports": [],
"boardTypes": []
},
"priceBandTolerancePercent": 15,
"includeManagementReport": true,
"reportLanguage": "en",
"alertAspectDeclineThreshold": 0.15,
"alertMinimumReviewCount": 3,
"notificationMode": "alerts",
"translateToEnglish": false,
"aiMaxRequests": 1000,
"aiMaxInputTokens": 5000000,
"useAiCache": true,
"proxyConfiguration": {
"useApifyProxy": false
}
}

startUrls accepts HolidayCheck /hr/, /hi/, /ho/, /hm/, /ha/, and contribution URLs when a hotel UUID is present.

Output records

The default dataset contains one normalized row per review.

The default key-value store contains:

  • OUTPUT: run summary, counters, feature usage, stop reasons, and failures
  • ASPECT_TRENDS: monthly hotel/aspect time series
  • COMPETITOR_SETS: target hotels, selected competitors, price comparisons, and exclusions
  • COLLECTION_STATE: a safe checkpoint summary without the full seen-ID arrays
  • MANAGEMENT_REPORT: portfolio-level management report and alerts
  • MANAGEMENT_REPORT.html: responsive, print-ready, email-ready report
  • MANAGEMENT_REPORT.txt: compact email and messaging digest
  • ALERTS: machine-readable action alerts
  • HEALTH: collection, price, AI, billing, and notification health checks

The named persistent state store contains the full collection state, daily anomaly baseline, exact trend-deduplication IDs, monthly aspect aggregates, and optional AI cache records.

Management report and alerts

Set includeManagementReport: true to create customer-facing artifacts without requiring the customer to read dataset JSON. reportLanguage supports en and de.

The report contains:

  • portfolio hotel and review counts;
  • per-hotel average rating, recommendation rate, and verified-reservation share;
  • the latest eight aspect scores, deltas, directions, and sample sizes;
  • target price versus comparable competitor median;
  • observable anomaly summaries;
  • prioritized, evidence-backed action alerts.

alertAspectDeclineThreshold controls the minimum monthly score drop on the -1 to 1 scale. alertMinimumReviewCount suppresses trend alerts from very small monthly samples.

Alerts do not declare reviews fake. They preserve the signal type, threshold, sample count, and supporting values for human investigation.

A real alert from a live run on 2026-07-28. The burst detector flagged 31 reviews with an elevated historical clustering signal (peak z-score 8.2), and the alert text itself states the boundary: it is a review hint, not a verdict about fake reviews:

{
"generatedAt": "2026-07-28T12:55:00.315Z",
"alerts": [
{
"id": "d5d6b6b58445b983",
"severity": "high",
"type": "review_burst",
"hotelId": "1aa4c4ad-f9ea-3367-a163-8a3a6884d450",
"hotelName": "Pickalbatros Dana Beach Resort - Hurghada",
"title": "ErhΓΆhtes Signal fΓΌr RezensionshΓ€ufung",
"message": "31 Rezensionen weisen ein erhΓΆhtes historisches HΓ€ufungssignal auf. Dies ist ein PrΓΌfhinweis, kein Urteil ΓΌber gefΓ€lschte Bewertungen.",
"evidence": {
"elevatedReviewCount": 31,
"highestZScore": 8.2
}
}
]
}

Signed notification webhook

Set an HTTPS notificationWebhookUrl to deliver a compact JSON digest to an owned email, Slack, Teams, Make, Zapier, or internal workflow. Set notificationWebhookSecret to add an HMAC-SHA256 signature over the exact request body.

notificationMode supports:

  • alerts: send only when the management report contains alerts;
  • always: send after every run that reaches reporting;
  • failures: send only when HEALTH.status is failed.

Use Apify platform lifecycle webhooks as well. They cover failures or timeouts that happen before the Actor reaches its own reporting phase.

This Actor is also exposed to AI agents through Apify's MCP server (mcp.apify.com): an agent can discover it by search and run it with the same pay-per-event billing, with no separate integration.

Pay-per-event billing

The code emits these custom value events:

  • review-result
  • competitor-set
  • price-intelligence-set
  • management-report

The event names and configured launch prices are documented in docs/APIFY_MONETIZATION.md. The Apify Actor uses review-result as its primary event and does not configure apify-default-dataset-item, because enabling both would bill the same delivered row twice.

OUTPUT.billing records the active pricing model, advertised per-event prices, delivered event counts, and spending-limit status.

Review row

{
"reviewId": "1ca1c304-88a6-4d19-9eba-b2fdae7eb503",
"hotelId": "1aa4c4ad-f9ea-3367-a163-8a3a6884d450",
"hotelName": "Pickalbatros Dana Beach Resort - Hurghada",
"reviewUrl": "https://www.holidaycheck.de/hr/1aa4c4ad-f9ea-3367-a163-8a3a6884d450#hotel-review-1ca1c304-88a6-4d19-9eba-b2fdae7eb503",
"title": "Gutes Hotel mit freundlichem Personal und schΓΆnem Pool",
"text": "(full review text in German, shortened here)",
"overallRating": 8.2,
"recommendation": true,
"verifiedReservation": true,
"entryDate": "2026-07-28T09:22:28.000Z",
"travelDate": "2026-07",
"travelerType": "COUPLE",
"originalLanguage": "de",
"returnedLanguage": "de",
"hotel": {
"id": "1aa4c4ad-f9ea-3367-a163-8a3a6884d450",
"name": "Pickalbatros Dana Beach Resort - Hurghada",
"stars": 5,
"starSource": null,
"rating6": 5.657160703601454,
"recommendationRate": 96.11,
"reviewCount": 28225,
"city": "Hurghada",
"region": "Hurghada/Safaga",
"country": "Γ„gypten",
"longitude": 33.83149,
"latitude": 27.096745
},
"reviewer": {
"hotelReviewCount": 1
},
"ownerResponse": null,
"topics": [],
"nativeRatings": {
"ROOM_SIZE": {
"label": "Zimmergrâße",
"sourceScore": 0.8,
"rating10": 8.2
},
"POOL_LOUNGER_RACE": {
"label": "VerfΓΌgbarkeit der Liegen",
"sourceScore": 1,
"rating10": 10
},
"RATING": {
"label": "Bewertung",
"sourceScore": 0.8,
"rating10": 8.2
},
"note": "10 more rated categories, shortened here"
},
"aspectScores": {
"room": {
"score": 0.733,
"label": "positive",
"confidence": "high",
"signalCount": 3,
"sourceSignals": [
{
"source": "rating",
"key": "ROOM_SIZE",
"score": 0.6
},
{
"source": "rating",
"key": "SLEEP",
"score": 1
},
{
"source": "rating",
"key": "ROOM_CLEANLINESS",
"score": 0.6
}
],
"evidence": []
},
"note": "7 more aspect dimensions, shortened here"
},
"aiAspectScores": null,
"aiAspectError": null,
"hybridAspectScores": "(hybrid aspect scores for the same dimensions, shortened here)",
"anomalySignals": null,
"translation": null,
"competitorSetRef": null,
"rawContributions": null,
"sourceUrl": "https://www.holidaycheck.de/hr/bewertungen-pickalbatros-dana-beach-resort-hurghada/1aa4c4ad-f9ea-3367-a163-8a3a6884d450",
"scrapedAt": "2026-07-28T10:14:10.261Z"
}

What the rows guarantee

The row above is a real verified stay from a live run on 2026-07-28; only free-text and repeated structures are shortened. Alongside it, the same run delivered this critical review:

{
"reviewId": "ee20b26c-d6b7-4272-aad5-ff3d3ac61940",
"hotelId": "1aa4c4ad-f9ea-3367-a163-8a3a6884d450",
"hotelName": "Pickalbatros Dana Beach Resort - Hurghada",
"reviewUrl": "https://www.holidaycheck.de/hr/1aa4c4ad-f9ea-3367-a163-8a3a6884d450#hotel-review-ee20b26c-d6b7-4272-aad5-ff3d3ac61940",
"title": "Service nach wie vor Top, ...",
"text": "(full review text in German, shortened here)",
"overallRating": 6.4,
"recommendation": false,
"verifiedReservation": true,
"entryDate": "2026-02-18T09:25:16.000Z",
"travelDate": "2026-02",
"travelerType": "COUPLE",
"originalLanguage": "de",
"returnedLanguage": "de",
"hotel": {
"id": "1aa4c4ad-f9ea-3367-a163-8a3a6884d450",
"name": "Pickalbatros Dana Beach Resort - Hurghada",
"stars": 5,
"starSource": null,
"rating6": 5.657160703601454,
"recommendationRate": 96.11,
"reviewCount": 28225,
"city": "Hurghada",
"region": "Hurghada/Safaga",
"country": "Γ„gypten",
"longitude": 33.83149,
"latitude": 27.096745
},
"reviewer": {
"hotelReviewCount": 116
},
"ownerResponse": null,
"topics": [
{
"id": "EVENING_PROGRAM",
"name": "Abendprogramm",
"sentiment": -1,
"quotes": [
"Hier kann man deutlich mehr machen.",
"Die Shows waren gefΓΌhlt fast tΓ€glich Tanzshows.",
"Das ist echt stinklangweilig, weil jeden Tag das Gleiche.",
"Die Bauchtanzshow war unterstes Niveau.",
"Die Abendshows fanden immer gegen 20.30 nach der Mini Disco stat."
]
},
{
"id": "ENTERTAINMENT",
"name": "Unterhaltung",
"sentiment": -1,
"quotes": [
"Einmal angeschaut, es gab soweit ich mich erinnere 5 Gewinne...alles Schrottpreise.",
"Der HΓΆhepunkt fΓΌr die Animation war es dann einmal wΓΆchentlich Lose fΓΌr eine Riesen Tombola zu verkaufen."
]
},
"(16 more topics, shortened here)"
],
"nativeRatings": {
"ROOM_SIZE": {
"label": "Zimmergrâße",
"sourceScore": 1,
"rating10": 10
},
"RATING": {
"label": "Bewertung",
"sourceScore": 0.6,
"rating10": 6.4
},
"FOOD_VARIETY": {
"label": "Essensauswahl",
"sourceScore": 0.4,
"rating10": 4.6
},
"note": "7 more rated categories, shortened here"
},
"aspectScores": {
"room": {
"score": 0.7,
"label": "positive",
"confidence": "high",
"signalCount": 6,
"sourceSignals": [
{
"source": "rating",
"key": "ROOM_SIZE",
"score": 1
},
{
"source": "rating",
"key": "SLEEP",
"score": 0.2
},
{
"source": "rating",
"key": "ROOM_CLEANLINESS",
"score": 1
},
{
"source": "topic",
"key": "ROOM",
"score": 1
},
{
"source": "topic",
"key": "ROOM_CLEANLINESS",
"score": 1
},
{
"source": "topic",
"key": "SLEEP",
"score": 0
}
],
"evidence": [
"Wir hatten auf Grund mehrerer Aufenthalte in dem Hotel ein upgrade auf ein Superiorzimmer im 2000er Block erhalten. \nGroß, sauber, riesen Dusche, Matratzen ungewohnt weich.",
"Aber da man ja wieder dankbar ist (darum geht es mir echt nicht) haben wir ein Upgrade fΓΌr ein Superior Zimmer beim nΓ€chsten Urlaub bekommen.",
"Groß, sauber, riesen Dusche, Matratzen ungewohnt weich."
]
},
"note": "7 more aspect dimensions, shortened here"
},
"aiAspectScores": null,
"aiAspectError": null,
"hybridAspectScores": "(hybrid aspect scores for the same dimensions, shortened here)",
"anomalySignals": null,
"translation": null,
"competitorSetRef": null,
"rawContributions": null,
"sourceUrl": "https://www.holidaycheck.de/hr/bewertungen-pickalbatros-dana-beach-resort-hurghada/1aa4c4ad-f9ea-3367-a163-8a3a6884d450",
"scrapedAt": "2026-07-28T10:15:56.087Z"
}
  • No cherry-picking. Critical reviews arrive with recommendation: false and their full rating breakdown, exactly like the positive ones.
  • Verification is reported, never implied. verifiedReservation is true only when HolidayCheck confirmed the stay; unverified reviews say so instead of hiding it.
  • Transparent normalization. nativeRatings keeps the raw sourceScore next to the derived rating10, so every normalized number can be recomputed from source.
  • Reviewer privacy by design. The reviewer object carries activity counts only; no names, avatars, or profile links are collected.

Eight aspect dimensions

Every aspect uses a -1 to 1 sentiment scale:

  1. room
  2. cleanliness
  3. service
  4. foodAndBeverage
  5. location
  6. amenities
  7. value
  8. familyAndEntertainment

aspectScores are deterministic. They map HolidayCheck rating contributions, topics, and quotes to stable dimensions. Each result includes confidence, source signals, and evidence.

When includeAiAspectScores is enabled, the Actor also analyzes the full title and review text. AI output uses a strict schema. A non-null AI score is retained only if at least one evidence string is an exact substring of the source review; unsupported or hallucinated evidence forces that aspect back to null.

hybridAspectScores is the final view:

  • native-only when only native evidence exists
  • AI-only when only validated AI evidence exists
  • weighted hybrid when both exist
  • unavailable when neither exists

The implementation uses the OpenAI Responses API with Structured Outputs:

https://developers.openai.com/api/docs/guides/structured-outputs

ASPECT_TRENDS.points contains one row per hotel, month, and aspect:

  • averageScore
  • reviewCount
  • availableScoreCount
  • positiveShare
  • previousMonthDelta
  • rollingThreeMonthAverage
  • direction: improving, stable, declining, or unavailable

Direction changes only when the month-over-month score delta is at least 0.1 in magnitude.

Monthly aggregates persist in the named state store. An incremental weekly run therefore retains earlier months and does not recalculate β€œsince March” trends from only the newest batch. Review IDs in the trend state prevent repeated schedules from double-counting a row.

Observable anomaly signals

The Actor does not label a review as fake. It returns source-level and sample-level evidence so the customer can make its own decision.

anomalySignals.signalVersion is observable-v2 and includes:

  • displayed verified-reservation status
  • displayed reviewer hotel-review count
  • single-review-profile flag
  • account-age value, availability status, and source
  • exact duplicate count in the run
  • near-duplicate count and nearest Jaccard similarity
  • same-day review count
  • same-rating run length
  • loaded hotel sample size
  • 90-day burst baseline, mean, standard deviation, z-score, and status
  • writing-pattern metrics:
    • characters, words, and sentences
    • average word and sentence length
    • unique and repeated word ratios
    • uppercase and punctuation ratios
    • exclamation and emoji counts
    • lexical entropy

HolidayCheck's current public review rows expose reviewer history depth but do not consistently expose a verifiable account creation date. In that case the Actor returns:

{
"accountAgeDays": null,
"accountAgeStatus": "unavailable",
"accountAgeSource": null
}

The field is never guessed from first-review dates or private assumptions.

The burst signal uses prior daily counts from the persistent state store plus other days in the current run. It remains insufficient_history until at least seven non-zero historical days are available.

Competitor and price intelligence

The automatic competitor pipeline:

  1. Deduplicates HolidayCheck alternatives from nearby, city, region, and country buckets.
  2. Keeps candidates in the same city or region when that context is available.
  3. Applies the configured star-class tolerance.
  4. Scores location, star similarity, distance, rating similarity, and review-volume similarity.
  5. Retains human-readable selectionReasons and source buckets.

Without live prices, the top similarity matches are selected.

With includePriceIntelligence: true, the Actor fetches the target and a wider candidate pool with one identical search context. It stores:

  • complete targetPrice
  • normalized total, nightly, and per-person prices
  • check-in/out, nights, occupancy, rooms, offer type, and currency
  • board, room, cancellation, provider, and offer ID when exposed
  • target price band, market median, and comparable count
  • each competitor's below, same_band, above, or unavailable relation

Only same_band competitors remain in competitors; rejected or unavailable candidates remain auditable in excludedCompetitors. The percentage boundary is configured with priceBandTolerancePercent.

An unavailable or rejected offer stays unavailable. The Actor never fabricates, carries forward, or currency-converts a price.

English translation and AI cost controls

Set translateToEnglish: true and supply either the secret openaiApiKey input or the OPENAI_API_KEY environment variable.

The translation pipeline:

  • preserves all original fields
  • translates title, full review text, and owner response
  • skips rows already marked English
  • batches calls and validates that every requested review ID returns exactly once
  • disables OpenAI response storage with store: false
  • sends only the required text fields, never reviewer-profile fields
  • can isolate failed batches and keep the source row

AI aspects and translation share:

  • aiMaxRequests
  • aiMaxInputTokens
  • useAiCache

The cache key includes feature version, model, and a SHA-256 hash of the relevant source content. OUTPUT.ai reports API calls, cache hits, tokens, failures, and budget-blocked batches.

The default model is gpt-5.6-luna, the lower-cost extraction/classification role in the GPT-5.6 family. The integration uses the Responses API, Structured Outputs, explicit reasoning.effort: "none", and store: false. Both AI features are disabled by default, and API usage is billed separately from the Actor run.

Failure and data semantics

  • A URL can fail independently when ignoreUrlErrors is true.
  • Page requests use bounded retries and configurable timeouts.
  • Price failures are row-level availability states, not fabricated zeroes.
  • AI failures can be isolated per batch.
  • Duplicate suppression uses HolidayCheck review IDs.
  • Temporary raw datasets are dropped after successful processing.
  • Originals are always preserved when AI features are enabled.

Verification

The V4 implementation is covered by 32 automated tests across 15 test files:

  • URL and input validation
  • Fluxible-state parsing
  • native aspect normalization
  • AI evidence validation, hybrid merging, cache, and budget limits
  • English translation and source-language skipping
  • anomaly writing, duplicate, near-duplicate, burst, and accumulator behavior
  • checkpoint resume, all, limit, and since collection modes
  • trend calculations
  • persistent cross-run trend aggregates and trend-level review-ID deduplication
  • competitor selection
  • comparable price-band selection
  • persistent baseline merging
  • in-page checkpoint continuation without lost rows
  • pay-per-event limits and event accounting
  • management report generation and HTML escaping
  • run-health classification
  • notification mode, delivery, and HMAC signing

A separate 30,000-review stress validation exercises streaming anomaly and trend accumulation:

$npm run test:stress

Local validation:

npm ci
npm run check
npm test
npm run test:stress
npm run test:live
npm run build
npm run preflight

npm run test:openai performs a real paid Structured Outputs smoke test only when OPENAI_API_KEY is present. npm run preflight -- --strict is the public Store release gate. Docker and a live OpenAI key are reported as optional validation capabilities; the strict gate remains closed until the explicit commercial-permission confirmation and Apify Store terms acceptance are present.

The included GitHub workflows run the deterministic CI suite and a weekly public-source contract smoke test. Operational setup is documented in docs/OPERATIONS.md.

Apify cloud build, controlled collection, and pay-per-event launch validation have completed successfully. Local Docker remains an optional secondary validation path.

Compliance

HolidayCheck states that its published content and data are legally protected, prohibits various forms of reuse including commercial exploitation, and provides info@holidaycheck.de for permission requests:

https://www.holidaycheck.de/haftungsausschluss

Use this Actor only when you have a lawful basis and every permission required for the intended use. Respect applicable terms, copyright and database rights, privacy law, request rates, and retention rules. This project does not provide legal advice and does not bypass authentication, CAPTCHAs, paywalls, or access controls.