TUI Scraper & Package Holiday Price Tracker - Pauschalreise avatar

TUI Scraper & Package Holiday Price Tracker - Pauschalreise

Pricing

from $1.40 / 1,000 package offers

Go to Apify Store
TUI Scraper & Package Holiday Price Tracker - Pauschalreise

TUI Scraper & Package Holiday Price Tracker - Pauschalreise

TUI scraper and package holiday price tracker: compare Pauschalreise offers across TUI, DERTOUR, weg.de, ab-in-den-urlaub.de and alltours in one dataset, with GIATA hotel matching, airport matrix, 90-day price history, buy-or-wait forecasts and price-drop alerts.

Pricing

from $1.40 / 1,000 package offers

Rating

0.0

(0)

Developer

Kamer Ozkan

Kamer Ozkan

Maintained by Community

Actor stats

0

Bookmarked

15

Total users

5

Monthly active users

2 days ago

Last modified

Share

Unofficial, independent price-monitoring tool. Not affiliated with, endorsed by, or sponsored by TUI, DERTOUR, weg.de, ab-in-den-urlaub.de, alltours, or any other travel provider.

Package holiday (Pauschalreise) price comparison and monitoring API for the German market: one search across TUI, DERTOUR, weg.de, ab-in-den-urlaub.de, and alltours returns normalized hotel + flight offers, same-hotel comparisons keyed by GIATA ID, departure-airport matrices, a deduplicated 90-day price history, market-availability signals, explainable buy-or-wait forecasts, and signed price-drop alerts to your webhook. Built for tour-operator pricing teams, OTAs, travel agencies, and travel-market analysts; it collects observations, not bookings.

What you can build with it

📉 1. A buy-or-wait desk for the destinations you sell

Schedule one run per day per destination with history, signals, and forecast switched on. The Actor keeps a deduplicated price series per stable package, scores availability narrowing from repeated observations, and emits an explainable buy_wait_forecast record (trend, volatility, days to departure, capacity evidence) instead of a black-box score.

{
"destination": "Antalya",
"startDate": "8 weeks",
"endDate": "10 weeks",
"nights": 7,
"adults": 2,
"departureAirports": ["DUS"],
"operators": ["tui", "dertour", "weg"],
"outputMode": "comparisons",
"history": { "enabled": true, "storeName": "antalya-watch" },
"signals": { "enabled": true },
"forecast": { "enabled": true }
}

🔔 2. Price-drop and capacity alerts to Slack, Make, or your CRM

Add alerts with up to five HTTPS webhooks. Deliveries are HMAC-signed, idempotent, cooldown-controlled (default 24 h per subject), and capped per run; only actually delivered alerts are billed. Alert types: price_drop, price_rise, availability_narrowing, source_recovery.

{
"alerts": {
"enabled": true,
"webhookUrls": ["https://hooks.example.com/package-prices"],
"types": ["price_drop", "availability_narrowing"],
"priceChangePercent": 5,
"cooldownHours": 24
}
}

🏨 3. Cheapest source for the same hotel, like for like

outputMode: "comparisons" returns one row per GIATA hotel with every source's cheapest offer side by side; comparisonMode: "like_for_like_package" additionally matches date, nights, occupancy, airport, room class, and board class, and matchQuality says per dimension what was matched exactly. Missing flight, baggage, transfer, or cancellation data stays explicit; nothing is invented.

✈️ 4. Departure-airport matrix for agencies and content teams

airportMatrix fans out one isolated search per requested airport (bounded by maxAirports, concurrency, and requestBudget) and emits comparable package prices by departure point, so a "from Düsseldorf vs. from Munich" table for the same hotel is one run.

Pricing and cost examples

Pay-per-event: the primary event is one normalized package offer; every optional layer has its own named event, so you pay only for the layers you switch on. Prices below are the FREE-tier rates effective 16 September 2026 (until 15 September 2026 the previous, lower rates on the pricing tab apply). Paid Apify plans get automatic tier discounts of up to 30%.

EventPriceWhat you get
📦 Package offer (primary)$0.002One normalized hotel + flight offer
🔎 Successful source search$0.015One source that returned results (failed searches are free)
🧮 Comparison row$0.002One GIATA hotel with all sources side by side
🗂️ History update$0.0005One new deduplicated observation in the 90-day series
✈️ Airport-matrix row$0.003One comparable price by departure airport
📊 Market signal$0.03One explainable availability-narrowing or price-jump signal
📉 Buy-or-wait forecast$0.03One explainable forecast record for a package series
🔔 Alert delivered$0.05One signed webhook delivery that actually reached your endpoint
🧾 Detail enrichment$0.004One evidence-backed offer-page lookup (cached)
▶️ Actor start$0.005 per GBOnce per run; the default 2 GB run is $0.01

Worked examples at the 16 September prices:

  • One-off comparison, Antalya, 5 sources x 20 offers with comparison rows: ≈ $0.33
  • Daily buy-or-wait desk, one destination, 3 sources, 10 offers, history + signals + forecasts: ≈ $0.40 per run → ≈ $12 per month
  • Alerting: each delivered price-drop or capacity alert adds $0.05; a quiet day costs nothing extra

Set a maximum cost per run and read OUTPUT.billing before raising result or matrix limits; the Actor stops work before your cap is exceeded.

Why use it?

  • Find the cheapest source for the same GIATA hotel with dachEntityId.
  • Compare Düsseldorf, Munich, Frankfurt, or other departure airports.
  • Build a deduplicated 90-day price curve for each stable package.
  • Detect narrowing market availability from repeated observations.
  • Create explainable buy/wait signals from price trend, volatility, days to departure, and availability evidence.
  • Send optional signed webhook alerts with cooldown and retry protection.
  • Keep partial results when one source is temporarily unavailable.

The Actor is built for tour-operator pricing teams, OTAs, travel agencies, and travel-market analysts. It collects observations, not bookings. A provider may revalidate price or availability at checkout.

Quick start

Use this minimum input:

{
"destination": "Antalya",
"startDate": "8 weeks",
"endDate": "10 weeks",
"nights": 7,
"adults": 2,
"childAges": [],
"departureAirports": ["DUS", "MUC"],
"operators": ["tui", "dertour", "weg", "aidu", "alltours"],
"outputMode": "comparisons",
"maxResultsPerOperator": 20
}

Dates accept either an absolute YYYY-MM-DD value or a rolling relative value such as 8 weeks. The Store form is prefilled with a valid rolling window so a new user can run the example without repairing stale calendar dates.

Results are written to the default dataset. OUTPUT in the default key-value store contains run status, record counts, source health, quality indicators, errors, feature summaries, cost telemetry, and billing operations.

Input parameters

Required fields are destination, startDate, endDate, and departureAirports. Everything else has a safe default, and every optional layer is off until you switch it on.

FieldDefaultWhat it does
destinationAntalyaCountry, region, or city, for example Mallorca, Hurghada, or Türkische Riviera
startDate / endDateform prefill 8 weeks / 10 weeksDeparture window as YYYY-MM-DD or a rolling value such as 8 weeks
nights7Trip duration
adults / childAges2 / []Occupancy; give each child's age on departure
departureAirports["DUS"]IATA codes such as DUS, MUC, FRA
operatorsall fivetui, dertour, weg, aidu (ab-in-den-urlaub.de), alltours
outputModeoffersoffers (one row per source offer) or comparisons (one row per GIATA hotel)
comparisonModelowest_offer_in_search_windowOr like_for_like_package for strict date, room, and board matching
maxResultsPerOperator20Caps normalized offers per source
sortpriceAscPrice order or the source's recommendation order
history, signals, forecastoff90-day price series, availability signals, buy-or-wait records
airportMatrixoffOne bounded search per departure airport
enrichmentoffCached offer-page lookups for baggage, transfer, and cancellation evidence
alerts, alertSigningSecretoffSigned HTTPS webhooks with cooldown
proxyConfigurationno proxyOptional Apify Proxy, used only for browser-backed retries

API and integrations

Run it from your own code with the Apify API and read the dataset when the run finishes:

curl -X POST "https://api.apify.com/v2/acts/kamerozkan~dach-package-holiday-price-api/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"destination":"Mallorca","startDate":"6 weeks","endDate":"8 weeks","nights":7,"adults":2,"departureAirports":["FRA"],"outputMode":"comparisons"}'
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("kamerozkan/dach-package-holiday-price-api").call(run_input={
"destination": "Hurghada",
"startDate": "8 weeks",
"endDate": "10 weeks",
"departureAirports": ["DUS", "MUC"],
"outputMode": "comparisons",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["recordType"], row.get("cheapestOperator"), row.get("cheapestTotalPrice"))
  • Schedules: create an Apify schedule for a daily watch; turn on history with a fixed storeName so every run adds to the same price series.
  • Webhooks: use the built-in alerts block for signed price-drop messages, or an Apify run webhook to trigger Make, Zapier, n8n, or your own endpoint when a run succeeds.
  • Exports: download the dataset as JSON, CSV, or Excel, or pull it into Google Sheets.
  • AI agents: the Actor is available through the Apify MCP server.

FAQ

Does it book trips or hold prices? No. It records public offers as observations. The provider may revalidate price and availability at checkout.

Which destinations work? Any destination the selected German portals sell as a package holiday. The Actor resolves the name per source; use destinationOverrides only when a name is ambiguous.

Why did one source return nothing? Each source is searched separately. A source without matching offers or with a temporary error is reported in OUTPUT and in a run_diagnostic row, and failed source searches are not charged. The other sources still deliver.

How do I compare the same hotel across portals? Set outputMode to comparisons. Rows are keyed by GIATA hotel ID (dachEntityId), so the same hotel lines up across sources.

How do I keep costs predictable? Keep maxResultsPerOperator small, switch on only the layers you need, and set a maximum cost per run. The Actor stops before the cap is exceeded.

Are prices per person or per booking? Both, when the source publishes them: price.total is the full package and price.perPerson is filled when available. Missing values stay null.

Live sources and evidence

SourceTransportHotel identityNotable evidence
TUI GermanyDirect JSONGIATAPrice, date, duration, room, board, discount
DERTOUR GermanyDirect JSONGIATAFlight legs, transfer, availability, flex marker
weg.deBrowser + intercepted JSONGIATAFlight, transfer, deal/flex markers, old price
ab-in-den-urlaub.deDirect JSONGIATAPrice, room/board, flex text; cashback is separate
alltoursPersisted GraphQLGIATAFlight, package operator, free cancellation, old price

Missing flight, baggage, transfer, cancellation, tax, or fee data remains explicit. The Actor does not invent unavailable fields. Optional, bounded weg.de detail enrichment can fill evidence-backed baggage, transfer, and flexible-cancellation fields and uses a persistent positive/negative TTL cache.

Comparison modes

  • lowest_offer_in_search_window compares the cheapest hotel offer returned by every selected source.
  • like_for_like_package additionally matches departure date, nights, occupancy, airport, normalized room class, and normalized board class.

Match-quality fields label exact, normalized, requested, mixed, and missing dimensions so downstream systems can decide what is comparable.

Dataset record types

  • offer
  • comparison
  • airport_matrix
  • price_series
  • market_signal
  • buy_wait_forecast
  • alert_delivery
  • run_diagnostic - emitted without a result charge when no primary rows can be written, so an empty search, partial source outage, and spending limit are immediately distinguishable.

Real records from live runs

The two records below are unedited engine output from live runs on 2026-07-28; only image lists and one very long source ID are shortened.

A real cross-operator comparison: the same GIATA-identified hotel, like-for-like window, three portals, and a real 27 EUR spread. matchQuality declares per dimension what was matched exactly and what was normalized, so a like-for-like claim is auditable instead of asserted:

A full offer record, including both flight legs as sold. Price honesty is structural: originalTotal, savingPercent, and taxesIncluded stay null when the portal does not publish them, and price.completeness says so explicitly. Hotel reputation fields are passed through as the source states them, even when they are unflattering (this 2-star property shows its single review and 0 percent recommendation as-is):

The full input is in examples/INPUT.json, a recurring watch is in examples/SCHEDULED_WATCH.json, and a normalized output sample is in examples/OUTPUT_OFFER.json.

Reliability and limits

  • Each source has typed errors, bounded retries, health summaries, and circuit breaking.
  • Airport matrix fan-out has explicit airport, concurrency, and request limits.
  • Explicit source-airport fallbacks are discarded when they do not match any requested IATA code, and the mismatch is reported in run diagnostics.
  • Price history is sharded, deduplicated, retained for 90 days by default, and stable across transient offer or flight identifiers.
  • Capacity scoring requires repeated observations and is suppressed when source coverage drops. It estimates market availability, not hotel occupancy.
  • Forecasts are informational signals, not price or booking guarantees.
  • HTTPS webhooks support HMAC signatures, idempotency keys, cooldowns, bounded retries, redirect blocking, and target-URL redaction.
  • alertSigningSecret is a top-level encrypted input and is mapped into the webhook runtime configuration without being emitted.
  • Pay-per-event guardrails stop work and output before the caller's maximum charge is exceeded.

The Store input defaults to proxy-free access. WEG tries direct browser access first and uses a configured Apify Proxy only on retry. Direct supplier API requests stay off the proxy; their browser fallbacks activate only when a direct source response is blocked or empty. Source APIs and persisted-query hashes can change; source-specific schema drift is reported without discarding successful sources.

Pricing

See "Pricing and cost examples" at the top of this page for the full event table and worked examples. Failed source searches, failed webhooks, cooldown-suppressed alerts, and duplicate history observations are never charged as successful events. Review the Store pricing tab, set a maximum cost per run, and inspect OUTPUT.billing before increasing result or airport-matrix limits.

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.

Privacy and lawful use

The Actor does not require traveller names, email addresses, payment details, or booking personal data. Child ages are optional search parameters. Webhook URLs and signing secrets remain within the caller's input and storage.

Users are responsible for lawful, proportionate use and compliance with applicable website terms, robots policies, database rights, privacy law, and contractual restrictions. Do not use the Actor to bypass access controls or overload source systems.

Support and feedback

  • Found a bug or missing a field? Open an issue on the Issues tab of this Actor. We reply within 48 hours and ship most fixes within a few days.
  • Have an idea for a feature? Issues are the fastest way to get it built.
  • If the Actor saves you time, a short review on this page helps other users find it.

Support and versioning

For reproducible schema drift or source failures, include the run ID, redacted input, affected source, and first error code. Upstream website changes are supported on a best-effort basis unless a separate SLA exists.

Breaking output changes use a major version; additive fields use a minor version; source fixes use a patch version. See CHANGELOG.md for release history.

Local development

Node.js 22.19 or newer is required.

npm install
npm run release:preflight
npm run release:live

For a local Apify run, place input at storage/key_value_stores/default/INPUT.json, then run:

$CRAWLEE_STORAGE_DIR="$PWD/storage" npm start

Price and date integrity maintenance, October 4, 2026

Required negative or nonfinite source totals are rejected by all five adapters and the comparison gate. Negative optional monetary values remain unknown; legitimate zero amounts are preserved. Provided source dates must be real Gregorian dates, and return-before-departure records are rejected. Missing dates stay unknown, with no requested-date substitution. Ninety-two focused offline cases and seventeen independent control groups passed with no source requests. Existing healthy normalized contracts match the prior version. This verification does not prove current provider access, availability, booking eligibility or customer revenue. Network access, dependency versions, input schema and pricing are unchanged.