Willhaben Marketplace Listings Scraper
Pricing
from $0.72 / 1,000 item extracteds
Willhaben Marketplace Listings Scraper
Export public Willhaben marketplace search cards with listing IDs, prices, locations, category attributes, preview text, dates and image references for Austrian inventory and price research.
Pricing
from $0.72 / 1,000 item extracteds
Rating
0.0
(0)
Developer
Automation Lab
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Export willhaben marketplace listings from anonymous kaufen-und-verkaufen search cards into a structured dataset for Austrian price and inventory research. Supply search URLs copied from Willhaben, including keyword, category or location filters. The Actor does not open listing details or require an account.
What does it extract?
Each result is one public marketplace search card, deduplicated by stable ad ID across the run. Data reflects the search response at retrieval time, not a historical archive.
| Fields | Meaning |
|---|---|
listingId, title, url | Stable ad identity, card heading and canonical listing link |
price, priceDisplay, currency | Numeric EUR amount when supplied, original displayed price and EUR |
location, postcode, district, state, country | Public locality context, without street address or coordinates |
categoryIds, categoryAttributes | Source category hierarchy and category-attribute ID encoding |
descriptionPreview | Search-card preview, not a full detail description |
publishedAt, changedAt | Source dates normalized to UTC, when available |
images | Public image references exposed in the search response; no downloads |
sellerType | Explicit private/business flag when present; no seller identity |
searchUrl, scrapedAt | Provenance search URL and retrieval timestamp |
Dates use the source's numeric millisecond epochs, not its *_String labels, which can contain Austrian local time mislabeled as UTC. Missing or invalid epochs return null; string-only dates are not guessed, including ambiguous daylight-saving transitions.
Missing optional scalars are null; absent lists are empty arrays. A zero price remains zero and is not treated as missing. Displayed prices may contain negotiability or nonstandard wording: keep priceDisplay alongside the numeric amount.
Who is it for?
- Resellers comparing asking prices for a product category in Austria.
- Analysts refreshing regional inventory snapshots.
- Researchers building repeatable price samples by keyword and location.
This is a search-card product, not a contact database, valuation engine or listing-detail enrichment service.
Why use this Actor?
It preserves the listing ID for joins between snapshots, retains displayed prices instead of inventing numeric values, and attaches source/retrieval dates. It avoids downloading images and opening every detail page. Global deduplication reduces duplicate exports from overlapping search URLs.
Getting started
- Open Willhaben's marketplace and apply your desired filters.
- Copy the HTTPS search URL, under
/iad/kaufen-und-verkaufen/marktplatz. - Paste it into Marketplace search URLs.
- Choose a global listing limit and a page cap per URL.
- Run the Actor and download the default dataset as JSON, CSV, Excel or another Apify-supported export.
{"startUrls": [{"url":"https://www.willhaben.at/iad/kaufen-und-verkaufen/marktplatz?keyword=lego"}],"maxItems": 30,"maxPages": 10}
Input parameters
| Parameter | Default | Semantics |
|---|---|---|
startUrls | Required | 1–20 marketplace search/category URLs, processed in order |
maxItems | 20 | Global maximum unique accepted listings; integer 1–10000 |
maxPages | 10 | Pages per starting URL; integer 1–100 |
Only URL-based GET search requests are supported. Custom request methods, payloads, headers, userData and remote request lists are rejected; optional empty fields are harmless. Native URL filters are forwarded to Willhaben unchanged. Keyword matching follows Willhaben's search behavior; there is no extra exact-phrase, substring or whole-word filter in this Actor. The Actor does not translate queries. Use the filters available on the source website rather than assuming arbitrary query parameter names work.
A URL's page is the starting page, defaulting to 1. The Actor always requests 30 cards per page, overriding a supplied rows. Global limits apply after deduplication, not separately to every source. Zero and unlimited are unsupported. Source exhaustion, page caps, run timeout or platform billing limits may stop collection before maxItems.
Output example
A representative search card, with public sample content simplified:
{"listingId": "937007997","title": "Lego Duplo (10848) 80 Stk.","url": "https://www.willhaben.at/iad/kaufen-und-verkaufen/d/lego-duplo-10848-80-stk-937007997/","price": 15,"priceDisplay": "€ 15","currency": "EUR","location": "Liezen","postcode": "8940","district": "Liezen","state": "Steiermark","country": "Österreich","categoryIds": ["5136", "5182", "5183", "5185"],"categoryAttributes": ["[2535;2537, 2535;2536, 21;2546, 5008971;5008972]"],"descriptionPreview": "Baustein-Set. 80 Teile.","publishedAt": "2026-10-19T19:59:21.000Z","changedAt": "2026-10-19T19:59:21.000Z","images": [],"sellerType": "private","searchUrl": "https://www.willhaben.at/iad/kaufen-und-verkaufen/marktplatz?keyword=lego&rows=30&page=1","scrapedAt": "2026-10-19T20:00:00.000Z"}
The key-value store's SUMMARY record contains saved listings, fetched pages, request attempts, retries and response bytes. These counters are included without extra billing.
How much does it cost to export Willhaben marketplace listings?
Pricing uses a one-time $0.003 start event per valid run and one item event per accepted unique listing saved to the dataset. The BRONZE item price is $0.001192 per listing ($1.192 per 1,000 listings). FREE is $0.0013708, SILVER $0.00092976, and GOLD/PLATINUM/DIAMOND $0.0007152 per listing. Spend tiers follow your qualifying aggregate monthly Apify Store spend, not a private per-Actor volume discount.
Worked example calculation (BRONZE): 10 listings cost $0.01492; 30 cost $0.03876; 100 cost $0.1222. These examples concern Actor event charges, not unrelated services or your subscription. Check the current Store pricing panel for your tier. A valid empty search has the start fee but no item events. Invalid input is rejected before the Actor's start charge. Duplicates and rejected records do not produce item events.
Pagination and completeness
The source is a changing marketplace: listings may move, expire or be promoted between page requests. IDs are deduplicated, but a run is not a transactionally consistent snapshot and cannot guarantee every listing. Start URLs are processed sequentially, so earlier URLs may consume the global limit. Date fields describe the source card; they are not proof that a change occurred since your previous run.
Use scheduled runs plus your own ID/date comparison if you need recurring research. The Actor itself stores no cross-run history and sends no change alerts.
Integrations
- Export to Google Sheets or a database through an Apify integration, joining by
listingId. - Schedule a category snapshot and compare price/date changes in your downstream pipeline.
- Send successful run notifications through Apify webhooks, then retrieve the default dataset.
- Build a regional inventory dashboard from
location,priceandscrapedAt.
Keep full exports in storage rather than passing thousands of descriptions directly into a language model.
API usage
Use your own Apify token as an environment variable; never put credentials into search URLs.
cURL
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~willhaben-marketplace-search-cards/runs' \-H "Authorization: Bearer $APIFY_TOKEN" -H 'Content-Type: application/json' \-d '{"startUrls":[{"url":"https://www.willhaben.at/iad/kaufen-und-verkaufen/marktplatz?keyword=lego"}],"maxItems":30}'
The asynchronous response contains a run ID and storage IDs, not listing rows. Follow that run until terminal success, then read its defaultDatasetId.
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/willhaben-marketplace-search-cards').call({startUrls: [{ url: 'https://www.willhaben.at/iad/kaufen-und-verkaufen/marktplatz?keyword=lego' }],maxItems: 30,});if (run.status !== 'SUCCEEDED') throw new Error(`Run ${run.id}: ${run.status}`);const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 30 });console.log(items);
Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/willhaben-marketplace-search-cards').call(run_input={'startUrls': [{'url': 'https://www.willhaben.at/iad/kaufen-und-verkaufen/marktplatz?keyword=lego'}],'maxItems': 30,})if run['status'] != 'SUCCEEDED':raise RuntimeError(f"Run {run['id']}: {run['status']}")print(client.dataset(run['defaultDatasetId']).list_items(limit=30).items)
MCP setup
Use an Actor-specific endpoint and authorized authentication in your client:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/willhaben-marketplace-search-cards"
Claude Desktop, Cursor, and VS Code configuration (where the client supports remote HTTP MCP):
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/willhaben-marketplace-search-cards"}}}
Discover the actual argument schemas with scoped tools/list. Actor selection also adds run/data helpers; it is not exactly one tool. Example prompts: “List the supported input fields without executing the Actor.” For an authorized run: “Export 30 Lego marketplace cards, then summarize displayed prices by locality.”
Start once and retain the run ID and storage IDs. If still running, follow that same run with bounded backoff (for example 2, 4, 8 seconds, capped at 10) and a total 120-second deadline. A start call may wait only 0–45 seconds, depending on its arguments. Set the client request timeout above that wait plus transport margin. If the client times out, recover the known run; do not restart blindly. At the deadline report pending with the run ID, or report terminal failure honestly.
After success, call get-dataset-items with the run's defaultDatasetId, initial offset=0, limit=20, and useful fields such as listingId,title,price,priceDisplay,location,publishedAt,changedAt,url,scrapedAt, using the argument types from scoped discovery. Use untransformed JSON and advance source offsets by the fetched page size. Fetch at most 100 source rows or 64 KiB of serialized UTF-8 results admitted to model context across all pages, whichever comes first. Enforce that byte budget host-side; omit or summarize oversized content with disclosure. Track source offsets, report truncation and continuation offset, and keep full exports outside model context. If your client cannot intercept oversized responses, do not claim a hard byte guarantee. No numeric token-saving claim is made.
Scope and limitations
- Only anonymous Austrian kaufen-und-verkaufen marketplace search cards.
- No vehicles, property, jobs, login, seller contact enrichment or detail-only fields.
- No raw seller IDs, profiles, street addresses or coordinates.
- Category attributes are source ID encodings, not translated labels or a complete detail specification.
- Preview text is not full description text. Obvious email and phone patterns are removed, but free-text redaction cannot guarantee anonymity.
- Image URLs may expire; the Actor does not download or archive media.
- No automatic proxy or browser fallback is enabled. A blocked source fails rather than pretending the search is empty.
FAQ and troubleshooting
Why are there no results? A valid recognized search with zero source matches returns no rows. Check the keyword and filters in a browser. Unsupported or missing search state is an error, not a successful empty export.
Why did the run fail? The Actor rejects unsupported URLs, malformed limits, redirects, blocked pages and invalid search state. Transient network/429/5xx failures receive at most two retries per page; permanent HTTP errors do not. A failure after earlier pages may leave partial rows, which should not be treated as a complete successful export.
Why fewer rows than requested? Check the per-URL page cap, source exhaustion, overlapping IDs, runtime and platform charge limits. The listing limit is a ceiling, not a guaranteed count.
Legality and diagnostic privacy
Use public data lawfully, respect Willhaben's terms and applicable privacy rights, and avoid contacting individuals or republishing personal information without a lawful basis. Public availability is not blanket permission for every downstream use. This Actor is independent and is not affiliated with Willhaben.
No AI model is used during extraction. Apify hosts runtime, storage and charging; source requests go directly to Willhaben, without an external scraping or proxy supplier. Runtime data remains in your run's Apify dataset/KV storage under your account's retention settings until deleted; no cross-run cache is maintained. Delete exports and runs in Apify when no longer needed. For product support, open the Actor's Store Issues tab with a run link and nonsensitive reproduction steps.
Failed operations send sanitized diagnostic input, exceptions and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed; reports are retained for 30 days. Do not put credentials or personal secrets into input.
Related Actors
For a different regional marketplace workflow, see Gumtree UK Classified Listings Scraper. It does not extend this Actor's Willhaben coverage.