Willhaben Vienna Real Estate Listings
Pricing
from $1.70 / 1,000 authorized willhaben listing evidence rows
Willhaben Vienna Real Estate Listings
Normalize buyer-owned, advertiser-authorized, partner-interface, or licensed Willhaben exports into stable evidence rows with property facts, freshness, gaps, review priority, and current-run settlement. No Willhaben login, scraping, API call, URL fetch, or automatic property decision.
Pricing
from $1.70 / 1,000 authorized willhaben listing evidence rows
Rating
0.0
(0)
Developer
Tim Zinin
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
11 days ago
Last modified
Categories
Share
Authorized Willhaben Listing Evidence
Turn property records you are authorized to use into consistent, evidence-backed review rows for operations, portfolio analysis, CRM intake, migration, and human decision queues.
This Actor is deliberately narrow. It does not log in to Willhaben, scrape a search page, call an undocumented endpoint, follow a listing URL, download an image, or pretend that a buyer attestation is independent verification. You supply the records and the rights context. The Actor validates, normalizes, deduplicates, scores evidence completeness, records limitations, delivers eligible rows, and writes a current-run settlement receipt.

What you get
For every accepted unique listing record, the Dataset contains one stable row with:
- a stable listing entity ID derived from the submitted Willhaben listing ID;
- preserved legacy property fields for existing Dataset consumers;
- buyer-supplied price, location, coordinates, dates, description, and image references where provided;
- an explicit source-context and rights statement;
observedAt,firstSeenAt, andlastSeenAtfor the current processing observation;- freshness derived only from the buyer-supplied
sourceRetrievedAttimestamp; - an evidence-completeness score, confidence band, basis, and gaps;
- a review priority and a specific next action;
safeToAutomate: falsebecause the Actor does not verify availability, ownership, legal status, condition, valuation, or transaction terms;- settlement-neutral billing intent in the row;
- authoritative run settlement in KVS
OUTPUT.
The product is useful when your team already possesses a lawful export or controlled record stream and needs to turn inconsistent objects into a predictable review contract. It is not a substitute for a licensed data source.
What it does not give you
The Actor does not provide:
- live Willhaben search results;
- access to Willhaben pages, accounts, feeds, or private APIs;
- proof that a listing is still published or available;
- verification of the advertiser, owner, agent, address, title, condition, energy certificate, or price;
- a property valuation, appraisal, legal opinion, investment recommendation, or purchase decision;
- historical change detection across runs;
- automatic lead outreach or CRM writes;
- identity enrichment or contact discovery;
- a licence to use data you do not already have permission to process;
- a guarantee that a recorded URL or image reference remains reachable.
If you need live source access, use an officially licensed feed or partner interface and submit its authorized export to this Actor. A public URL by itself is not evidence of downstream commercial rights.
Who uses it
This Actor is designed for teams that already control the input records and need a reliable processing layer:
- advertisers and agencies normalizing their own published-property exports;
- property managers consolidating authorized portfolio records;
- brokerages using a partner interface within its contractual scope;
- licensed data providers delivering a bounded downstream dataset;
- portfolio analysts preparing a human review queue;
- integration teams migrating legacy property pipelines without silently continuing an unlicensed collector.
It is not designed for anonymous bulk collection, lead harvesting, contact discovery, copying an entire marketplace, or obtaining data rights after the fact.
Deutschsprachige Kurzfassung
Dieser Actor ruft weder Willhaben-Seiten noch eine Willhaben-API ab. Er verarbeitet ausschließlich Datensätze, die der Käufer selbst besitzt, vom Inserenten erhalten hat, über eine zulässige Partner-Schnittstelle bezieht oder aufgrund einer anderen Lizenz verarbeiten und weitergeben darf. Die Bestätigung im Input ist eine Erklärung des Käufers; sie wird vom Actor nicht unabhängig geprüft.
Jeder akzeptierte Datensatz erhält eine stabile ID, einen Bearbeitungszeitpunkt, eine nachvollziehbare Frischeeinschätzung, Evidenz-Digests, Datenlücken, Konfidenzbasis und eine ausdrückliche Empfehlung zur menschlichen Prüfung. safeToAutomate bleibt immer false. Der Actor bestätigt weder Verfügbarkeit, Eigentum, Identität des Inserenten, Zustand, Marktwert noch rechtliche Verwendbarkeit eines Objekts.
Abgerechnet wird nur eine tatsächlich zugestellte, berechtigte Evidenzzeile über result-found; Migrations- und Validierungshinweise sind hinsichtlich dieses Ergebnis-Events kostenlos. Der aktuelle KVS-Datensatz OUTPUT ist die maßgebliche Quelle für Zustellung, Zahlung, Teilverarbeitung und Wiederholungssicherheit. Bei unklarem Zustellungs- oder Zahlungsstatus darf der Lauf nicht blind wiederholt werden.
Portfolio intake
Normalize records received from an advertiser, property manager, partner interface, or licensed data vendor before they enter a portfolio database. Stable IDs and closed fields make downstream reconciliation easier than accepting arbitrary spreadsheets.
Listing evidence review
Create a human-review queue that shows what was supplied, what is missing, how fresh the supplied source timestamp appears, and which checks still require an authorized source or a person.
Migration from legacy search inputs
Existing integrations may still send deal_type, city, max_items, and max_pages. Those fields remain accepted so old callers do not crash at schema submission. They no longer trigger a source request. The Actor delivers one clearly labeled free migration diagnostic explaining how to move to listings.
CRM or warehouse staging
Use the Dataset as a controlled intermediate layer. The Actor does not write to a CRM and does not claim that its output is import-ready for every account. Your own review and mapping rules remain authoritative.
Licensed feed normalization
When a partner feed is available, set sourceContext to willhaben_partner_interface_export, keep the partner-provided source and rights text, and submit only the fields your agreement permits you to retain and redistribute.
How the workflow works

- You submit authorized records. The input includes a fixed authorization statement, a source-context category, and one to 100 listing objects.
- The Actor validates a closed contract. Unknown properties, malformed values, unsafe URL shapes, impossible UTC timestamps, and out-of-range numbers are rejected at record level.
- It normalizes and deduplicates. Listing IDs are trimmed and compared case-insensitively. The first valid occurrence is retained.
- It builds evidence rows. Legacy property fields are preserved, while the additive evidence layer describes identity, freshness, confidence, gaps, action, and limitations.
- It checks the run budget. The automatic Actor-start charge is already part of current spend. Each planned paid result is checked against the buyer's run cap before a linked push.
- It delivers with a named event. An eligible row is pushed with
result-found. The Actor requires the named counter to move by exactly+1and the linked SDK receipt to match the Dataset-plus-result event contract. - It records terminal truth. Current-run KVS
OUTPUTreconciles input, work, Dataset writes, paid/free/withheld rows, unknown outcomes, budget stop, fatal error, and replay safety. - A person decides what happens next. The Actor always emits
safeToAutomate: false.
There are zero source network requests in this workflow. Recorded listing and image URLs are data fields, not fetch instructions.
How to run
Use the Store Input tab or submit JSON through the Apify API.
{"schemaVersion": "2.0","authorization": "I confirm I am authorized to process and deliver these Willhaben listing records","sourceContext": "advertiser_authorized_export","listings": [{"listingId": "authorized-vienna-1001","listingUrl": "https://www.willhaben.at/iad/immobilien/d/mietwohnungen/wien/wien-1020-leopoldstadt/authorized-example-1001/","title": "Authorized Vienna apartment evidence","price": 1290,"currency": "EUR","dealType": "rent","propertyType": "Wohnung","rooms": 2,"areaSqm": 54.5,"location": "Wien, 2. Bezirk, Leopoldstadt","latitude": 48.216,"longitude": 16.392,"postedAt": "2026-08-12T08:30:00Z","description": "Buyer-supplied minimal listing summary with unnecessary personal contact data removed.","images": [],"sourceName": "Advertiser-authorized listing export","sourceLicense": "Buyer confirms authorization to process and deliver this listing record.","sourceRetrievedAt": "2026-08-13T00:00:00Z"}]}
The authorization sentence is exact. It is an attestation from the caller. The Actor records it as part of the request contract but does not independently prove it.
Input contract
The current contract version is 2.0.
| Field | Required for listing mode | Contract |
|---|---|---|
schemaVersion | No | Must be 2.0 when present. |
authorization | Yes | Must equal the displayed authorization statement exactly. |
sourceContext | Yes | One of the four documented authorized-export categories. |
listings | Yes | 1–100 closed listing records. |
deal_type | Legacy only | Migration diagnostic only; never used for a request. |
city | Legacy only | Migration label only; never used for a request. |
max_items | Legacy only | Accepted for compatibility; it does not start collection. |
max_pages | Legacy only | Accepted for compatibility; it does not start collection. |
The Actor input-schema dialect cannot express the root rule “modern listing mode or legacy diagnostic mode” as a full JSON Schema oneOf. Runtime validation is therefore the normative second stage. Mixing listings with legacy fields is rejected.
Source contexts
Choose the category that most accurately describes your record origin:
buyer_owned_listing_export— records controlled by the buyer;advertiser_authorized_export— records supplied or authorized by the advertiser;willhaben_partner_interface_export— records obtained through an authorized Willhaben partner interface;other_licensed_property_export— another property data export with rights covering this processing and delivery.
These values are categories, not verification badges. Keep the actual agreement or authorization in your own records. Use sourceName and sourceLicense to preserve a concise, non-secret provenance statement.
Listing fields
| Field | Required | Limits and meaning |
|---|---|---|
listingId | Yes | 1–160 characters; letters, digits, _, and -. Used for stable identity and deduplication. |
listingUrl | No | HTTPS www.willhaben.at/iad/immobilien/d/... reference. No credentials, port, or fragment. Never fetched. |
title | Yes | Nonblank, up to 500 characters. |
price | Yes, nullable | null or a finite number from 0 to 10,000,000,000. |
currency | Yes, nullable | Three letters when price is supplied; normalized to uppercase. Must be null with a null price. |
dealType | Yes | rent or sale. |
propertyType | No | Nonblank when supplied, up to 160 characters. |
rooms | No | Finite number from 0 to 100. |
areaSqm | No | Finite number from 0 to 10,000,000. |
location | No | Nonblank when supplied, up to 300 characters. |
latitude | No | Finite number from -90 to 90. |
longitude | No | Finite number from -180 to 180. |
postedAt | No | Real UTC timestamp ending in Z, up to 40 characters. |
description | No | Nonblank when supplied, up to 1,000 characters. Minimize personal and confidential data. |
images | No | Up to five unique HTTPS references. They are recorded and never fetched. |
sourceName | Yes | Nonblank source label, up to 200 characters. |
sourceLicense | Yes | Nonblank rights statement, up to 700 characters. Do not put secrets or entire agreements here. |
sourceRetrievedAt | No | Real UTC timestamp ending in Z, up to 40 characters. |
A record that passes the public JSON shape but fails the closed runtime semantic contract is not silently converted into a paid listing. The Actor counts those rejected records and writes one free diagnostic for the run. Inputs rejected by Apify's public schema never reach the runtime. Valid unique records in the same request can still proceed.
Deduplication
Deduplication is by normalized listingId, case-insensitively, within the current input. For example, VIENNA-1001 and vienna-1001 represent one requested entity. The first valid occurrence is retained.
This is not cross-run idempotency. Submitting the same record in a new run can produce a new paid delivery. Use your own stable request ledger and inspect the current-run OUTPUT before deciding whether to run again.
Legacy migration behavior
The following old input remains syntactically accepted:
{"deal_type": "mietwohnungen","city": "wien","max_items": 5,"max_pages": 1}
It produces exactly one free run_advisory row with:
found: false;failureType: "legacy_search_input";recommendedAction: "MIGRATE_TO_AUTHORIZED_LISTING_EXPORT";billing.billingEligible: false;- no
result-foundevent; source.networkRequestsMade: 0in KVSOUTPUT.
This compatibility path keeps older callers observable without claiming that a search occurred. It should be treated as a migration warning, not as listing data.
Field dictionary
The current listing row keeps the legacy property shape and adds a decision-quality layer.
Preserved property fields
Existing consumers can continue reading:
found, url, title, price, currency, deal_type, property_type, rooms, area_sqm, location, lat, lng, posted_date, description, images, source_portal, scraped_at, partial, partial_reason, note, and error.
The name scraped_at is preserved for backward compatibility. In contract 2.0.0, it equals the processing observation time. It does not mean the Actor scraped Willhaben.
Additive evidence fields
| Field | Meaning |
|---|---|
contractVersion | Row contract version 2.0.0. |
recordType | willhaben_authorized_listing_evidence or run_advisory. |
stableId | SHA-256 identity based on source family and lowercase listing identity key. |
entityId | Human-readable willhaben-listing:<lowercase-listingId> identity; the preserved listingId keeps the submitted casing. |
observedAt | Current Actor processing timestamp. |
freshness | Buyer-supplied source timestamp classification, age, basis, and observation time. |
change | Always not_measured for the single submitted snapshot. |
confidence | Evidence completeness level, basis, and explicit gaps. |
evidence | Digests of the submitted record, rights statement, and recorded URL when present. |
confidenceScore | Completeness score reduced by documented gaps; not an accuracy score. |
dataGaps | Missing fields and unverified claims that require review. |
recommendedAction | REVIEW_LISTING_EVIDENCE for listing rows. |
priority | Review ordering based on supplied freshness and location evidence. |
safeToAutomate | Always false. |
failureDiagnostics | Structured diagnostic for free advisory rows, otherwise null. |
billing | Settlement-neutral delivery eligibility and intent. |
requestDigest | Digest of the normalized current request. |
inputDigest | Digest of the normalized listing object. |
Why confidence is not accuracy
The score measures how much of the expected evidence shape the caller supplied. A high score does not prove the listing is real, current, accurately priced, legally marketable, or suitable for a buyer. The Actor does not compare the record with Willhaben or another authoritative source.
Freshness states
fresh—sourceRetrievedAtis no more than 24 hours before processing;recent— more than 24 hours and no more than seven days;older— more than seven days;unknown— no source retrieval time was supplied, or the supplied time is in the future.
Freshness is explicitly based on the buyer-supplied timestamp. It is not a live-source check.
Evidence and boundaries
The evidence layer answers a narrow operational question: “What normalized facts did the authorized caller submit, how complete are they, and what remains unverified?” It does not answer “Is this property currently available?” or “Should we transact?”
Evidence digests bind normalized values for reconciliation. They are useful for detecting accidental mutation between input, Dataset and KVS workflows. They do not prove that the underlying statement is true and do not replace a source licence, title document, signed advertiser instruction or current authorized-source check.
The Actor explicitly records these recurring gaps even for a complete-looking row:
- buyer-supplied export not independently verified;
- listing identity, availability and advertiser rights not independently verified;
- condition, valuation and transaction terms not verified.
Missing optional fields add more specific gaps. Downstream consumers should preserve rather than suppress them.
Decision routing
Every listing route is human-review-only:
HIGHpriority means the supplied source timestamp is fresh and a location was supplied;MEDIUMcovers recent, unknown or incomplete evidence that still warrants review;LOWmarks older supplied evidence;recommendedActionremainsREVIEW_LISTING_EVIDENCE;safeToAutomateremainsfalseat every confidence level.
Priority controls queue order, not business outcome. It must not be converted into automatic outreach, tenant screening, valuation, purchase, rejection, legal notice or financial action.
Commercial playbooks
Advertiser portfolio QA
Submit the advertiser's own export, group by dataGaps, and review fresh high-priority rows first. Use the receipt to prove how many unique records were delivered. Resolve content gaps in the system of record; do not treat Actor normalization as a source correction.
Licensed feed staging
Submit one bounded feed batch with the correct source context and licence label. Persist runId, requestDigest, Dataset ID and KVS ID in the ingestion ledger. Promote rows downstream only after paid/free/withheld counts and the named event reconcile.
CRM review queue
Map stable IDs and core property facts into a staging object, not directly into customer-facing automation. Keep confidence gaps and safeToAutomate visible. A human confirms identity, authorization, contact policy and next step.
Legacy integration migration
Run the existing city/deal payload once to receive the free migration diagnostic. Replace the upstream collector with an authorized export, then switch to contract 2.0. Do not loop the legacy diagnostic or call it a zero-result market search.
Vienna and Austrian property data notes
The Actor does not normalize Austrian legal classifications, district identifiers, cadastral data, energy performance, operating costs, deposits, commissions or tenancy law into verified fields. location, propertyType, price, rooms and areaSqm retain buyer-supplied meaning. Currency normalization only uppercases a three-letter code; it does not establish that every amount is an all-in monthly rent or total purchase price.
Vienna district text, coordinates and descriptions can create precise location and personal-data risk. Submit the minimum precision needed for the authorized purpose. Verify German-language source terms, abbreviations and transaction components in the licensed source or original documents before operational use.
Dataset views
The default overview view combines listing rows and diagnostics so operators can see outcomes rather than only successful rows.
The listingEvidence view shows accepted listing evidence, including price, property attributes, recorded references, freshness, confidence, gaps, source label, and next action.
The diagnostics view isolates free migration and validation rows. It keeps failure reasons visible instead of hiding them in raw JSON.
Nested values use JSON-oriented display where appropriate. Recorded listing URLs use link display; image references remain JSON rather than loading third-party images in the Dataset table.
Pricing
The Actor uses Apify pay-per-event billing with two event names:
apify-actor-start— the automatic run-start unit;result-found— one delivered authorized Willhaben listing evidence row.
Current six-tier prices are:
| Tier | Actor start | One result-found row |
|---|---|---|
| FREE | $0.00500 | $0.00200 |
| BRONZE | $0.00475 | $0.00190 |
| SILVER | $0.00450 | $0.00180 |
| GOLD | $0.00425 | $0.00170 |
| PLATINUM | $0.00410 | $0.00164 |
| DIAMOND | $0.00400 | $0.00160 |
The start event is separate. A free diagnostic means “no result-found charge for that row,” not “the whole run is free.”
Paid unit
The paid unit is exactly one accepted unique listing evidence row delivered through a linked Dataset push with the named result-found event.
The Dataset row itself contains billing intent, not final settlement. It uses:
{"billingEligible": true,"billingIntent": "linked_push_result_found","eventName": "result-found","unit": "one delivered authorized Willhaben listing evidence row","settlementSource": "current_run_kvs_output"}
KVS OUTPUT is the authoritative current-run settlement record.
Free outcomes
No result-found event is intentionally emitted for:
- legacy search migration diagnostics;
- invalid-record diagnostics;
- duplicates removed before row construction;
- records withheld before a paid push because the run cap cannot cover the next unit;
- pre-push pricing or counter failures.
The automatic start event still applies to a hosted run.
Exact settlement proof
For every paid operation, the Actor requires:
- the named
result-foundcounter before the operation to equal the number already confirmed in this run; - the linked Dataset push to return;
- the named counter to increase by exactly
+1; - the linked SDK receipt to account for the Dataset write plus named result event (
chargedCount: 2); eventChargeLimitReachedto be a boolean.
eventChargeLimitReached: true can accompany a valid final paid row. It means another result at the same price cannot fit; it does not turn the current confirmed row into a free row.
If the SDK confirms that no event fits, it returns chargedCount: 0, the named counter stays unchanged, and no Dataset row is written. The Actor records confirmed_withheld, stops, and reports the remaining work as withheld.
Budget behavior
The Actor reads the platform run cap and current charged amount. On hosted runs it requires the current spend to include the exact tier's automatic start price. Before each result, it checks the next result price in integer microdollars.
If the next unit does not fit:
- no paid push is attempted for that record;
budgetStoppedbecomestrue;- remaining valid records are counted as withheld;
- the terminal status is
PARTIAL, not a fabricated success; - already confirmed rows remain valid.
An unlimited platform cap is supported explicitly. Malformed pricing, a wrong event map, a string price, an unknown tier, an unreadable initial counter, or a nonzero initial named counter fails closed before paid delivery.
KVS OUTPUT
Every terminal path attempts to write the current-run receipt under the exact key OUTPUT.
The receipt includes:
- current platform
runId; - normalized
requestDigest; - requested, unique, duplicate, invalid, and legacy-input counts;
- attempted, successful, failed, delivered, paid, free, and withheld counts;
- unknown-delivery and unknown-settlement counts;
- partial and budget-stop flags;
- fatal error and replay safety;
- named-event counters before and after;
- confirmed event delta and Dataset writes;
- last-attempt settlement facts;
- explicit source mode and
networkRequestsMade: 0; - Dataset URL;
- start and completion timestamps;
- primary/recovery KVS status and terminal exit state.
The semantic validator recomputes the work and delivery partitions. It rejects impossible combinations such as a paid count without a named counter delta, a free diagnostic with a result event, a complete status with withheld work, or a replay-safe receipt after any Dataset push attempt.
Example terminal shape
The exact IDs and timestamps vary by run, but a one-row successful hosted run has this structure:
{"schemaVersion": "2.0.0","kind": "authorized_willhaben_listing_output","status": "COMPLETE","runId": "CURRENT_PLATFORM_RUN_ID","input": {"requestedCount": 1,"uniqueCount": 1,"duplicateCount": 0,"invalidCount": 0,"legacyInputCount": 0},"run": {"attemptedCount": 1,"successfulCount": 1,"failedCount": 0,"deliveredRowCount": 1,"paidRowCount": 1,"freeRowCount": 0,"withheldRowCount": 0,"unknownDeliveryCount": 0,"unknownSettlementCount": 0,"partial": false,"budgetStopped": false,"fatalError": null,"replaySafe": false,"safeToAutomate": false},"delivery": {"eventName": "result-found","attemptedPushCount": 1,"resultChargeCountBefore": 0,"resultChargeCountAfter": 1,"confirmedEventDelta": 1,"confirmedDatasetWrites": 1},"source": {"mode": "buyer_authorized_export_only","networkRequestsMade": 0,"platformLoginUsed": false,"sourceContext": "advertiser_authorized_export"}}
The full record also contains requestDigest, lastAttempt, errors, resultsUrl, timestamps, and the terminal KVS/exit lattice.
Delivery ambiguity and replay safety
The Actor does not blindly retry a linked paid push.
- If the push throws, Dataset delivery and settlement may both be unknown. The run fails with
unknown_deliveryandreplaySafe: false. - If the push returns but the post-push named counter is unreadable, Dataset delivery may be known from the bounded receipt while charge settlement remains unknown. The run fails with
settlement_unknownandreplaySafe: false. - If counters and the aggregate receipt contradict one another, the run fails with
settlement_anomalyandreplaySafe: false. - If failure occurs before any push attempt, the receipt remains replay-safe for result delivery, although a new hosted run still incurs a new automatic start event.
Do not rerun an ambiguous operation automatically. Inspect the Dataset, platform charged-event counters, and KVS receipt for the recorded run. A new run is a new billable operation, not an idempotent replay of the old one.
Happy, partial, and failure output
The following two review receipts are deterministic local contract fixtures. They are not claims about a live canary, customer, or current production run. Final Store acceptance replaces the local identifiers with the exact immutable build, run, Dataset, KVS, pricing, and browser evidence.
Happy authorized-listing fixture:
{"buildId": "local-contract-fixture-v2","runId": "local-test-willhaben-run","status": "SUCCEEDED","evidenceAccepted": true,"dataset": {"recordType": "willhaben_authorized_listing_evidence","entityId": "willhaben-listing:authorized-vienna-1001","safeToAutomate": false,"recommendedAction": "REVIEW_LISTING_EVIDENCE","billing": {"billingEligible": true,"billingIntent": "linked_push_result_found","eventName": "result-found","settlementSource": "current_run_kvs_output"}},"output": {"status": "COMPLETE","runId": "local-test-willhaben-run","input": {"requestedCount":1,"uniqueCount":1,"duplicateCount":0,"invalidCount":0,"legacyInputCount":0},"run": {"attemptedCount":1,"successfulCount":1,"failedCount":0,"deliveredRowCount":1,"paidRowCount":1,"freeRowCount":0,"withheldRowCount":0,"unknownDeliveryCount":0,"unknownSettlementCount":0,"partial":false,"budgetStopped":false,"fatalError":null,"replaySafe":false,"safeToAutomate":false},"delivery": {"eventName":"result-found","attemptedPushCount":1,"resultChargeCountBefore":0,"resultChargeCountAfter":1,"confirmedEventDelta":1,"confirmedDatasetWrites":1},"source": {"mode":"buyer_authorized_export_only","networkRequestsMade":0,"platformLoginUsed":false,"sourceContext":"advertiser_authorized_export"},"terminal": {"outcome":"COMPLETE","failureStage":null,"primaryKvsWrite":"confirmed","recoveryKvsWrite":"not_attempted","exit":"requested"}}}
Legacy migration fixture:
{"buildId": "local-contract-fixture-v2","runId": "local-test-willhaben-legacy-run","status": "SUCCEEDED","evidenceAccepted": true,"dataset": {"recordType": "run_advisory","failureType": "legacy_search_input","found": false,"partial": true,"recommendedAction": "MIGRATE_TO_AUTHORIZED_LISTING_EXPORT","billing": {"billingEligible":false,"billingIntent":"free_diagnostic_dataset_write","eventName":null,"settlementSource":"current_run_kvs_output"}},"output": {"status": "PARTIAL","runId": "local-test-willhaben-legacy-run","input": {"requestedCount":0,"uniqueCount":0,"duplicateCount":0,"invalidCount":0,"legacyInputCount":1},"run": {"attemptedCount":0,"successfulCount":0,"failedCount":0,"deliveredRowCount":1,"paidRowCount":0,"freeRowCount":1,"withheldRowCount":0,"unknownDeliveryCount":0,"unknownSettlementCount":0,"partial":true,"budgetStopped":false,"fatalError":null,"replaySafe":false,"safeToAutomate":false},"delivery": {"eventName":"result-found","attemptedPushCount":1,"resultChargeCountBefore":0,"resultChargeCountAfter":0,"confirmedEventDelta":0,"confirmedDatasetWrites":1},"source": {"mode":"legacy_migration_diagnostic_only","networkRequestsMade":0,"platformLoginUsed":false,"sourceContext":null},"terminal": {"outcome":"PARTIAL","failureStage":null,"primaryKvsWrite":"confirmed","recoveryKvsWrite":"not_attempted","exit":"requested"}}}
| Status | Meaning |
|---|---|
COMPLETE | All accepted unique records were delivered and settled as paid results; no diagnostics or withheld work remain. |
PARTIAL | Some work was diagnostic, rejected, duplicate, withheld, or budget-stopped, but no fatal settlement or runtime error remains. |
FAILED | A pricing, current run/Dataset identity, delivery, settlement, KVS, exit, or input contract failure prevents a trustworthy successful terminal claim. |
The Actor writes one bounded recovery OUTPUT after a primary KVS write or exit failure. It does not loop indefinitely. If both KVS writes fail, the platform run failure remains the only durable terminal signal.
Privacy and data minimization
Property records can contain personal data even when they look like ordinary listings. Free-text descriptions, URLs, image references, building details, coordinates, and internal source notes may identify an advertiser, tenant, owner, or household.
Before submitting data:
- confirm that your purpose and source rights cover this processing and downstream delivery;
- remove names, phone numbers, email addresses, access codes, tenant information, and confidential terms unless strictly necessary and authorized;
- avoid private documents and non-public location details;
- do not place tokens, signed URLs, session IDs, API keys, or credentials in any field;
- use a retention period appropriate to the purpose;
- provide correction and deletion handling in your own downstream system;
- restrict Dataset and KVS access to the people who need it;
- do not use the result for discriminatory housing decisions, harassment, profiling, or automated legal decisions.
Apify stores Actor input and output as part of the run. A field marked secret in a UI is not a reason to submit data that your workflow should not retain. This Actor has no secret input field and does not need a Willhaben login or API key.
SHA-256 digests help reconcile exact normalized values. They do not anonymize predictable identifiers or make personal data non-personal.
Sources and rights
The caller is responsible for having the necessary rights to process and deliver every submitted record and reference. Suitable origins can include buyer-owned records, an advertiser-authorized export, a Willhaben partner interface used within its agreement, or another licensed property export.
The Actor does not test whether a licence is valid, transferable, current, complete, or sufficient for a specific downstream purpose. It does not transform public availability into permission. sourceLicense is a concise buyer-supplied statement, not a legal finding by the Actor.
Keep the actual contract, consent, partner terms, or authorization outside the Dataset. Do not paste confidential agreements into sourceLicense.
Security boundary
This version has no network fetch path. It does not resolve submitted hosts, follow redirects, load images, execute supplied URLs, authenticate to a platform, or open a browser.
The runtime accepts a Willhaben listing URL only as a bounded recorded reference. Image references must use HTTPS but are not fetched or independently verified. Downstream consumers must treat all text and URLs as untrusted data and escape them before rendering.
The input and Dataset contracts are closed. Unknown input properties are rejected, strings are bounded, control characters are rejected at runtime, numeric ranges are bounded, and UTC dates are calendar-validated.
Integration recipes
Replace ACTOR_ID and APIFY_TOKEN in your own environment. Keep tokens out of code, logs, input fields, and screenshots.
curl -X POST \"https://api.apify.com/v2/acts/ACTOR_ID/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \--data-binary @input.json
Poll the returned run ID to terminal, then read:
- the default Dataset for delivered listing evidence and diagnostics;
- default KVS record
OUTPUTfor authoritative current-run reconciliation; - platform charged-event counters for independent settlement confirmation.
Do not infer success from HTTP acceptance of the run request. A run is accepted only after its exact terminal status, Dataset, KVS OUTPUT, logs, and charged events reconcile.
Python-style orchestration
The same sequence applies from any SDK: start one run with an explicit charge cap, poll that exact run ID, read its Dataset and OUTPUT, compare the returned runId, then reconcile charged events. Avoid convenience wrappers that automatically retry failed POSTs or start a second run after an ambiguous response.
MCP and agent workflows
An agent may prepare input and summarize review gaps, but it should not autonomously assert source rights, raise safeToAutomate, or decide to rerun an ambiguous delivery. Keep the Actor input and OUTPUT as machine-readable evidence and place approval for any business action in a separate human-controlled step.
Operating guide
Before production use:
- Store the exact source agreement or authorization outside the Actor input.
- Remove unnecessary personal and confidential data.
- Keep an internal request ID and the Actor run ID together.
- Submit no more than 100 records per run.
- Set a run charge cap that covers the automatic start event plus the maximum intended result units.
- Wait for a terminal run state.
- Read KVS
OUTPUTbefore consuming Dataset rows. - Require
runIdto match the platform run. - Reconcile
confirmedDatasetWrites,paidRowCount,freeRowCount, and named event counts. - Stop for manual reconciliation on
unknown_delivery,settlement_unknown, orsettlement_anomaly. - Do not automatically rerun an ambiguous operation.
- Keep
safeToAutomate: falsein downstream decision logic.
FAQ
Does this Actor scrape Willhaben?
No. Contract 2.0 makes zero Willhaben requests. Listing and image URLs are recorded references only.
Why is Willhaben in the product name?
The Actor normalizes records that refer to Willhaben listing identity and preserves the established Actor identity for existing users. It does not imply sponsorship, endorsement, partnership, or source access.
Can I paste a Willhaben search URL?
No. The current contract accepts authorized listing records, not search URLs. Legacy city/deal fields produce only a free migration diagnostic.
Are buyer attestations verified?
No. The Actor records the source context and rights statement, checks their shape, and makes the limitation visible. Your organization remains responsible for authorization.
Is a high confidence score proof that the listing is correct?
No. It is an evidence-completeness score. The Actor does not independently verify the submitted content.
Does the Actor decide whether to rent, buy, contact, or invest?
No. It recommends human review and always sets safeToAutomate: false.
Why can a Dataset row say billing-eligible before settlement is known?
Because the row is constructed before the linked platform settlement finishes. The row describes intent. Current-run KVS OUTPUT is the authority for paid, free, withheld, anomalous, or unknown settlement.
What happens to duplicates?
Duplicate valid listing IDs within one request are removed before row construction. They are counted in input.duplicateCount and do not intentionally emit result-found.
What happens to invalid records?
If they reach runtime and fail the closed semantic contract, they contribute to input.invalidCount. The run emits one free diagnostic covering that count. Inputs rejected by the public Apify schema never reach runtime. Valid unique records may still be processed.
Can I submit price 0?
Yes, because 0 can be an explicit buyer-supplied value. It is not interpreted as market truth. Use null when price is not supplied, with currency: null.
Are image URLs downloaded?
No. Up to five HTTPS references can be recorded. The Actor does not fetch, validate ownership of, or display those images in the Dataset view.
Does the Actor track changes between runs?
No. change.status is not_measured. Build a separate authorized history layer if you need change detection.
Can I automatically retry a failed run?
Only a receipt with zero push attempts is replay-safe for result delivery. Even then, a new hosted run incurs a new start event. Never blindly retry after a push attempt.
Where is the final run truth?
Read the current run's KVS OUTPUT, then reconcile it with the platform run status, Dataset, and charged-event counters.
Product boundary in one sentence
Authorized Willhaben Listing Evidence converts records you already have the right to use into a transparent human-review contract; it does not obtain those rights, fetch the source, verify the market, or make the decision for you.