# willhaben Scraper (`lowlanddata/willhaben-scraper`) Actor

willhaben.at is Austria's largest marketplace, and it keeps no export and no price history, everything lives inside the search page you refresh by hand. Rows give price in cents, the seller's own display price, posting date, city, postcode, district and Bundesland. No seller identity collected.

- **URL**: https://apify.com/lowlanddata/willhaben-scraper.md
- **Developed by:** [Lowland Data](https://apify.com/lowlanddata) (community)
- **Categories:** E-commerce, Automation, Business
- **Features:** Limited permissions
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## willhaben Scraper

willhaben.at is Austria's largest marketplace, and everything about it happens inside a search page: no export, no history, no way to see last week's prices. Tracking what a category is worth, or waiting for one listing at the right price, is done by refreshing the tab.

Any willhaben search comes back as rows: price in cents next to the seller's own display price, posting and last-changed dates, city, postcode, district and Bundesland, and whether the ad is private or commercial. Put it on a schedule and you keep the price history the site does not keep for you.

**Live health record:** [lowlanddata.com/status/willhaben-scraper](https://lowlanddata.com/status/willhaben-scraper/) - 30-day success rate and daily canary results, failures included. Full input/output reference: [tool page](https://lowlanddata.com/tools/willhaben-scraper/).

No login, no CAPTCHA solving, no private endpoints: the actor reads what willhaben shows a logged-out visitor. The only seller field is whether the listing is from a business or a private seller; names, identifiers and exact map coordinates are not collected.

### Quick start (30 seconds)

1. Put what you'd type in the willhaben search box into **searchQuery**, e.g. `fahrrad`.
2. Click **Start**. That's the whole minimum setup.
3. When the run finishes, open the dataset's **Overview** tab for a clean table, or **Export** it as CSV/Excel/JSON.

Optional knobs: a price band in euros and newest-first sorting for monitoring, and any input works on a daily Schedule.

### What you can build with it

- **Watch a niche for underpriced listings.** Run `searchQuery: "e-bike"` with `priceMaxEur: 800` and `sortBy: "date"` hourly; every new listing arrives with `priceCents` parsed and the seller's own display price (`priceDisplay`) kept for reference.
- **Map prices by region.** Every listing carries `city`, `postcode`, `district` and `state`: chart what the same bike costs in Wien versus Steiermark without touching a map coordinate.
- **Track business vs. private supply.** The `sellerType` flag on every listing tells you how much of any category is professional traders, market structure no willhaben page shows you.
- **Feed an AI agent or a pipeline.** Every field is structured and predictable, so an assistant can consume it directly with no parsing step.

### What you get

Each listing is one dataset item:

```json
{
  "listingId": "2098800001",
  "url": "https://www.willhaben.at/iad/kaufen-und-verkaufen/d/fahrrad-18-zoll-2098800001/",
  "title": "Fahrrad 18 Zoll",
  "description": "Wir verkaufen das Fahrrad, da es zu klein geworden ist.",
  "priceCents": 5000,
  "currency": "EUR",
  "priceDisplay": "€ 50",
  "postedAt": "2026-08-21T08:47:26Z",
  "changedAt": "2026-08-21T08:47:26Z",
  "city": "Sinabelkirchen",
  "postcode": "8261",
  "district": "Weiz",
  "state": "Steiermark",
  "sellerType": "private",
  "status": "active",
  "imageUrls": ["https://cache.willhaben.at/mmo/2/209/880/0001_-11.jpg"]
}
```

Field notes, so you know exactly what you are buying:

- `priceCents` is the numeric asking price in euro cents; `priceDisplay` is exactly what the site shows, which also covers "zu verschenken" and similar non-numeric prices (then `priceCents` is absent).
- `postedAt` vs `changedAt`: sellers edit and bump listings; `changedAt` is why an older listing can appear near the top of a newest-first run.
- Location is municipality-level: `city`, `postcode`, `district`, `state`. willhaben's data contains exact coordinates; they are deliberately never collected.
- `description` is the search-page text, truncated to about 256 characters. Turn on **Fetch full descriptions** (`scrapeDetails`) to replace it with the seller's full text, read from each ad's own page. Contact attributes are never read, so no seller contact is added.
- `status` is the site's own word for the listing's state, `active` or `reserved` as willhaben reports it (a listing that is sold or taken down is no longer on the site at all). `imageUrls` carries every photo of the listing, in the site's order.

### How much does it cost to scrape willhaben?

$3.00 per 1,000 listings delivered, pay-as-you-go: no subscription, and you pay per result rather than per hour. A run that finds nothing still costs the $0.005 actor start. In plain dollars:

- **100 listings ≈ $0.30**, a daily niche watch.
- **500 listings ≈ $1.50**, a solid market snapshot.
- **A 5,000-listing crawl ≈ $15.00**, a broad category, deduplicated.

The price is all-inclusive: your runs' platform usage is covered by it, with no separate compute or proxy charges. Runs are fast; a scoped few-hundred-item run typically finishes in under ten seconds. Datacenter proxies are sufficient, no residential proxy surcharge needed.

Free-plan runs are limited to a sample of 5 items, enough to evaluate the output format against your real query.

### Not technical? Let your AI assistant set it up

Copy this into ChatGPT, Claude or any AI assistant, fill in the one line, and follow the conversation:

```text
Help me set up the "willhaben Scraper" actor on Apify
(https://apify.com/lowlanddata/willhaben-scraper). Guide me one step at a time.

What I want to watch: [E.G. "e-bikes under 800 euros in Styria"]

Guide me to:
1. Propose my input values: searchQuery (what I'd type in the willhaben search box),
   an optional priceMinEur/priceMaxEur band, sortBy "date" for newest-first
   monitoring, and maxItems.
2. Create a free Apify account (apify.com), open the actor page, paste the values
   into the Input form, and start a run.
3. Set up a daily Schedule in the Apify Console with the same input, plus an email
   or Slack integration so new results reach me automatically.
4. Show me how to export results as CSV/Excel, or read them from the API if I code.
5. If the results are what I wanted, remind me at the end to leave a quick rating on the actor page, and to report anything broken or missing on its Issues tab.
```

### Input

| Field                | Description                                                                                                                                                                                                                                                                                                                                                                                                                   |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `searchQuery`        | What you'd type in the willhaben search box. Required, unless you only re-check listings through `listingIds`.                                                                                                                                                                                                                                                                                                                |
| `listingIds`         | Re-check listings you already know instead of searching: ad IDs (the number at the end of every ad address, the `listingId` of every row) or the ads' full addresses, one per line. Each is read from its own page with the full description, every photo and the site's own `status`. A listing that is gone from the site is skipped, named in the log and not billed. When given, the search fields are ignored. Up to 50. |
| `priceMinEur`        | Only listings costing at least this many euros.                                                                                                                                                                                                                                                                                                                                                                               |
| `priceMaxEur`        | Only listings costing at most this many euros.                                                                                                                                                                                                                                                                                                                                                                                |
| `sortBy`             | `date` (newest first, default), `price_asc`, `price_desc`, or `relevance`.                                                                                                                                                                                                                                                                                                                                                    |
| `postedAfter`        | Only listings posted on or after this date (YYYY-MM-DD). Stops early with newest-first sorting.                                                                                                                                                                                                                                                                                                                               |
| `postedBefore`       | Only listings posted on or before this date (YYYY-MM-DD).                                                                                                                                                                                                                                                                                                                                                                     |
| `maxItems`           | Stop after this many listings (default 1000).                                                                                                                                                                                                                                                                                                                                                                                 |
| `scrapeDetails`      | `true` replaces the truncated description with the seller's full text, read from each ad's own page (default off). One extra request per listing.                                                                                                                                                                                                                                                                             |
| `proxyConfiguration` | Proxy settings; keep Apify proxy enabled.                                                                                                                                                                                                                                                                                                                                                                                     |

A run minimally needs a `searchQuery` or a list of `listingIds`; invalid combinations (like an inverted price band) fail immediately with the reason in the run's status message.

#### Re-checking listings you already have

Put their IDs (or their addresses) into `listingIds` and nothing else: the run reads each ad's own page and returns it in the usual shape - same fields, same `url`, same spelling as a search result - with the full description, every photo and the site's own `status`, whether or not `scrapeDetails` is on. A price change shows up as a new `priceCents`; a listing the seller has marked reserved comes back with `status: "reserved"`; one that has been sold, has expired or was taken down is not on the site any more - the run skips it, says so in the log and the status, and does not bill it. Schedule such a run and you have a watch on the exact listings you care about. This covers Marktplatz ads (kaufen-und-verkaufen); car ads live on a different part of the site that refuses datacenter exits, so use the [willhaben Car Scraper](https://apify.com/lowlanddata/willhaben-car-scraper) for those.

### Use it from your code

Run the actor and get items straight back with one HTTP call (fine for scoped runs up to ~5 minutes):

```bash
curl "https://api.apify.com/v2/acts/lowlanddata~willhaben-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -X POST -H "Content-Type: application/json" \
  -d '{"searchQuery": "fahrrad", "maxItems": 100}'
```

Node.js:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('lowlanddata/willhaben-scraper').call({
  searchQuery: 'fahrrad',
  maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("lowlanddata/willhaben-scraper").call(
    run_input={"searchQuery": "fahrrad", "maxItems": 100})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

For bigger crawls, start the run asynchronously and fetch the dataset when the finished-run webhook fires. Schedules (e.g. a daily price snapshot), webhooks and the Make/Zapier/n8n integrations all work out of the box: this is a standard Apify actor.

### Use it with AI agents (MCP)

Claude, Cursor and other MCP-capable agents can run this scraper as a tool through Apify's hosted MCP server: the agent fills in the search itself, starts the run and reads the results (no glue code).

Claude Code:

```bash
claude mcp add apify --transport http "https://mcp.apify.com?actors=lowlanddata/willhaben-scraper"
```

Cursor or Claude Desktop (add a custom connector / MCP server with this URL):

```text
https://mcp.apify.com?actors=lowlanddata/willhaben-scraper
```

**Want the whole family at once?** Point one connector at every tool in the EU Marketplaces bundle:

```text
https://mcp.apify.com?actors=lowlanddata/kleinanzeigen-scraper,lowlanddata/marktplaats-scraper,lowlanddata/tweedehands-scraper,lowlanddata/olx-pl-scraper,lowlanddata/olx-ro-scraper,lowlanddata/olx-pt-scraper,lowlanddata/willhaben-scraper,lowlanddata/finn-no-scraper,lowlanddata/tori-fi-scraper,lowlanddata/blocket-se-scraper,lowlanddata/dba-dk-scraper,lowlanddata/gumtree-uk-scraper,lowlanddata/vinted-scraper,lowlanddata/bol-com-scraper,lowlanddata/subito-scraper,lowlanddata/bazos-cz-scraper,lowlanddata/bazos-sk-scraper,lowlanddata/olx-bg-scraper,lowlanddata/olx-ua-scraper,lowlanddata/willhaben-car-scraper,lowlanddata/kleinanzeigen-free-finds,lowlanddata/olx-listing-watch,lowlanddata/marktplaats-new-listing-alerts,lowlanddata/tweedehands-new-listing-alerts,lowlanddata/kleinanzeigen-deal-radar
```

Sign in with your Apify account when prompted: runs are billed to it. Setup details per client: [Apify MCP docs](https://docs.apify.com/platform/integrations/mcp), or start from this actor's own MCP page: [apify.com/lowlanddata/willhaben-scraper/api/mcp](https://apify.com/lowlanddata/willhaben-scraper/api/mcp).

Prompts that work once connected:

- "Search willhaben for e-bikes under 800 euros and summarize prices by Bundesland."
- "Get the 100 newest 'iphone 15' listings from willhaben and flag private sellers below the median price."
- "Watch willhaben for 'wohnmobil' and tell me when something under 25 000 euros appears."

### How deep does a crawl go?

willhaben's search pages go very deep: this actor pages through results at 90 listings per page until it reaches your `maxItems` or the end of the results, deduplicating by listing id. For very broad market crawls, split by price bands (`priceMinEur`/`priceMaxEur`) across runs; overlapping runs merge cleanly on `listingId`.

### Is it legal to scrape willhaben?

Public listing data (prices, descriptions, categories, locations) is public commercial information, and this scraper is built so that the hard part of the question never arises: **no personal data enters your dataset in the first place.** Austria's data-protection authority (DSB) applies the same GDPR baseline as the rest of the EU; an output that carries none of the seller's personal data is the point of this actor, not an afterthought.

Structurally, the extractor maps a fixed whitelist of attributes out of the page's data. The advertiser block, the seller identifiers and the exact coordinates are never read into the output; the only seller-derived value is the business-vs-private flag. Requests are paced, load on the site is kept negligible, and no anti-bot protection is bypassed.

One honest limit: titles and descriptions are the seller's own words, delivered as-is. If a seller chooses to type contact details into their listing text, that text is not rewritten; the guarantee covers the data fields, not the content sellers publish about themselves.

This actor is an independent tool. It is not affiliated with, endorsed by or sponsored by willhaben or its owners, and trademarks belong to their respective holders.

### Is there a willhaben API alternative?

willhaben publishes no public API for reading listings. This actor is the practical alternative: the same listings as structured JSON through one HTTP call (`run-sync-get-dataset-items`), on a schedule, or as an MCP tool for AI agents, with the GDPR question already answered in the data itself.

### Does willhaben block scrapers?

willhaben serves its listings openly to ordinary requests, and this actor stays inside that welcome: paced requests, standard datacenter proxies, load kept negligible. No CAPTCHA fights, no bot-wall cat-and-mouse, which is also why runs are fast and reliable enough for daily schedules.

### How do I monitor willhaben prices?

Set `sortBy: "date"` with your query, cap `maxItems` to a page or two, and add a daily (or hourly) Schedule in the Apify Console with an email/Slack integration on the runs: every new listing lands in your inbox with the price already parsed to cents. The AI-assistant prompt above walks a non-technical user through exactly this setup. Even tighter: set `postedAfter` to yesterday's date; the dataset then contains only the new listings, nothing to dedupe on your side.

### FAQ

**Can I get seller names or phone numbers?** No, by design. That is the product: data you can store, share and process without a GDPR review. The output tells you only whether the seller is a business or a private person.

**Why does an old listing show up in a newest-first run?** Sellers edit and bump listings; compare `postedAt` with `changedAt` to tell fresh listings from bumped ones.

**Does it cover cars and property too?** This actor searches willhaben's Marktplatz (general goods). Cars and property live in willhaben's own verticals with different data: candidates for separate actors, done properly.

**Can I get only the newest listings?** Yes: set `postedAfter` to a date (yesterday, say) and the dataset contains only listings posted since then. With newest-first sorting the run stops paging as soon as it provably reaches older listings, so a daily watch stays fast and cheap.

**How fresh is the data?** Live at run time: every run queries willhaben directly. For continuous freshness, schedule the actor.

**Can I export to Excel or CSV?** Yes: every dataset exports as CSV, Excel, JSON or XML from the Apify Console or API.

**Does it work with Make, Zapier or n8n?** Yes: it is a standard Apify actor; all platform integrations, webhooks and schedules apply.

**Can I scrape willhaben without an API key?** Yes. willhaben offers no public read API to get a key for; the actor runs on your Apify account alone, and the free tier is enough for a trial run.

**What does it cost to scrape willhaben?** $3.00 per 1,000 listings delivered, pay-as-you-go. A run that finds nothing still costs the $0.005 actor start; the price covers your runs' platform usage, nothing comes on top.

**Do I need residential proxies for willhaben?** No: datacenter proxies work for the vast majority of runs. The form's own example input is pinned to residential so your very first run is guaranteed clean regardless; switch back to datacenter for your real searches once you've seen the output shape. There is no residential surcharge hiding in the price either way.

**How long does a run take?** Seconds, not minutes: a scoped few-hundred-item run typically finishes in under ten seconds, which is what makes hourly schedules practical.

**How do I scrape only listings from the last day?** Set `postedAfter` to yesterday's date. With newest-first sorting the run stops paging as soon as it provably reaches older listings: a daily watch stays small and cheap. `postedBefore` bounds the other end; both take YYYY-MM-DD or a full ISO timestamp.

**Why is priceCents missing on some listings?** The seller set a non-numeric price such as "zu verschenken". `priceDisplay` always carries exactly what the site shows, so nothing is lost.

**Does the output include GPS coordinates?** No: willhaben's data contains exact coordinates, and this actor deliberately never collects them. You get `city`, `postcode`, `district` and `state`, which is enough for regional price maps.

**How many listings can one run collect?** The actor pages through results at 90 listings per page until `maxItems` or the end, deduplicating by `listingId`. For very broad market crawls, split across runs with price bands; overlapping runs merge cleanly on the id.

**What if willhaben blocks the run partway?** Everything collected before the block is kept and delivered, with the partial coverage stated in the run status. You pay only for delivered listings; a later re-run or a narrower query usually completes.

**Why did I only get 5 results?** You are on the Apify free plan, which caps this actor at a 5-item sample. Any paid plan lifts the cap to your `maxItems`.

**Can ChatGPT or Claude search willhaben for me?** Yes, connected through Apify's hosted MCP server, an AI agent can pick the search terms, run the actor and reason over the results in one conversation.

**How is this better than searching willhaben myself?** The site shows you pages; this actor gives you data: prices parsed to cents, posting timestamps, the business-vs-private split per listing, and one-click CSV/Excel export, all repeatable on a schedule.

**Is there a scraper like this for Germany or Poland?** Yes, the Kleinanzeigen.de and OLX.pl scrapers listed below, built on the same GDPR-clean output discipline.

**Is it legal to scrape willhaben?** Listing data (prices, descriptions, municipality-level locations) is public commercial information, and this actor's whitelist mapper keeps every seller identifier and exact coordinate out of the output, so no personal data reaches your dataset.

### Related scrapers

Working the European second-hand market? Same output discipline, same public health record:

- [Kleinanzeigen.de Scraper](https://apify.com/lowlanddata/kleinanzeigen-scraper), Germany's biggest classifieds site.
- [OLX.pl Scraper](https://apify.com/lowlanddata/olx-pl-scraper), Poland's largest classifieds marketplace.
- [Marktplaats.nl Scraper](https://apify.com/lowlanddata/marktplaats-scraper), the Netherlands' biggest marketplace.

### Troubleshooting

The actor fails fast with the reason in the run's status message:

- **"priceMinEur must not be higher than priceMaxEur."**: swap the two values.
- **"willhaben blocked the run before any results could be fetched. This is usually temporary - retry in a few minutes."**: a temporary block on the first request; a retry usually lands on a clean proxy session.
- **"... then the site blocked further requests. Partial coverage ..."**: the run kept everything collected before the block; re-run later or narrow the query.
- **Fewer items than requested on a free plan**: the 5-item free sample cap; run on a paid Apify plan for full results.

### Support

Found an issue or missing a field you need? The fastest route is the actor's **Issues tab** - it is monitored and reports get fixed. For anything private, email **contact@lowlanddata.com**. This actor is actively maintained.

Working well for you? A **rating on this page** takes ten seconds and helps other buyers find it; it is also the clearest signal of what we should build next.

# Actor input Schema

## `searchQuery` (type: `string`):

What to search for on willhaben's Marktplatz, exactly as you would type it in the site's search box, e.g. "fahrrad" or "iphone 15". Leave it out when you only re-check listings through <b>listingIds</b>.

## `listingIds` (type: `array`):

Re-check listings you already know instead of searching: one ad ID per line (the number at the end of every ad address, and the <code>listingId</code> of every dataset item), or the ad's full address. Each one is read from its own page, so it carries the full description, every photo and the site's own <code>status</code> (active, reserved, ...) whether or not <b>Fetch full descriptions</b> is on. A listing that is gone from the site is skipped, named in the log and not billed. Marktplatz ads only; car ads belong to the willhaben Car Scraper. <b>When given, the search fields of this form are ignored</b> and the run status says which. Up to 50.

## `priceMinEur` (type: `integer`):

Only include listings costing at least this many euros.

## `priceMaxEur` (type: `integer`):

Only include listings costing at most this many euros.

## `sortBy` (type: `string`):

Order of results: date (newest first, best for monitoring), price_asc, price_desc, or relevance.

## `postedAfter` (type: `string`):

Only include listings posted on or after this date. With newest-first sorting the run stops early once older listings are reached. <b>Format: <code>YYYY-MM-DD</code></b> (for example <code>2026-09-08</code>) or a full ISO timestamp such as <code>2026-09-08T14:30:00Z</code>. Slash dates like <code>08/09/2026</code> are refused on purpose: they are read as September in Europe and August in the United States, and this actor will not guess which you meant.

## `postedBefore` (type: `string`):

Only include listings posted on or before this date. <b>Format: <code>YYYY-MM-DD</code></b> (for example <code>2026-09-08</code>) or a full ISO timestamp such as <code>2026-09-08T14:30:00Z</code>. Slash dates like <code>08/09/2026</code> are refused on purpose: they are read as September in Europe and August in the United States, and this actor will not guess which you meant.

## `maxItems` (type: `integer`):

Stop after this many listings. Free-plan runs are capped at 5 items. The form starts at 25 for a cheap first run - that is the form's prefill, not a cap on your plan; clear it to use the default of 1000.

## `scrapeDetails` (type: `boolean`):

The search truncates the description to about 256 characters. Turn this on to read each ad's own page for the seller's full description. This makes one extra request per listing, so a run is slower and costs one more page fetch each. Only the description text reaches the output; contact attributes are never read. Leave off for a fast search-only sweep.

## `proxyConfiguration` (type: `object`):

Proxy settings. Keep Apify proxy enabled.

## `reportFailures` (type: `boolean`):

When a run fails, send the developer the actor name and build, an error category, the error message (truncated) and a one-way hash of your input - so a bug can be fixed without anyone asking you to reproduce it. <b>Your input itself, your results and your identity are never sent, and successful runs send nothing at all.</b> Switch this off and the actor behaves exactly the same.

## Actor input object example

```json
{
  "searchQuery": "fahrrad",
  "listingIds": [],
  "sortBy": "date",
  "maxItems": 25,
  "scrapeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "reportFailures": true
}
```

# Actor output Schema

## `listings` (type: `string`):

Scraped willhaben listings, one JSON object per listing.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQuery": "fahrrad",
    "listingIds": [],
    "sortBy": "date",
    "maxItems": 25,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lowlanddata/willhaben-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQuery": "fahrrad",
    "listingIds": [],
    "sortBy": "date",
    "maxItems": 25,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("lowlanddata/willhaben-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQuery": "fahrrad",
  "listingIds": [],
  "sortBy": "date",
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call lowlanddata/willhaben-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lowlanddata/willhaben-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/B016BejXeBJIje5Yv/builds/PS3rLzckR8TPem91T/openapi.json
