{"description":"Searches Kleinanzeigen (formerly eBay Kleinanzeigen) like the site's own search page. Returns up to 25 listings per page with a numeric price, VB (negotiable) and free flags, postcode and district, posting date, seller type and link. Third-party sponsored ads are removed; paid 'top' listings are kept and marked promoted.","effect":"read","id":"kleinanzeigen.de/search-listings","keywords":["kleinanzeigen","ebay kleinanzeigen","gebraucht","kaufen","anzeigen suchen","flohmarkt","second hand","used","classifieds","marketplace","listings","buy used"],"output":{"schema":{"properties":{"listings":{"items":{"properties":{"description":{"description":"Truncated description snippet","type":["string","null"]},"district":{"type":["string","null"]},"free":{"description":"Zu verschenken","type":"boolean"},"id":{"type":"string"},"image_url":{"type":["string","null"]},"negotiable":{"description":"VB (Verhandlungsbasis)","type":"boolean"},"posted_date":{"description":"Set for older listings; null when the site only says today/yesterday","format":"date","type":["string","null"]},"posted_relative":{"enum":["today","yesterday",null]},"posted_time":{"description":"HH:mm, Europe/Berlin, for today/yesterday listings","type":["string","null"]},"price_eur":{"description":"null when no price is given or the item is free","type":["number","null"]},"price_text":{"description":"Price exactly as the site shows it","type":["string","null"]},"promoted":{"description":"Paid top listing, pinned above the sort order","type":"boolean"},"seller_type":{"enum":["private","commercial",null]},"shipping":{"description":"Seller offers shipping","type":"boolean"},"title":{"type":"string"},"url":{"format":"uri","type":"string"},"zip":{"type":["string","null"]}},"type":"object"},"type":"array"},"location":{"description":"Resolved place label, or 'Deutschland' when no location was given","type":"string"},"page":{"type":"integer"},"query":{"type":"string"},"total":{"description":"Total hits reported by the site (all pages)","type":["integer","null"]}},"required":["query","location","page","total","listings"],"type":"object"},"value":"let $h = steps.search.heading || '' in {query: params.query, location: steps.location.name || 'Deutschland', page: params.page, total: contains($h, 'keine Ergebnisse') && `0` || to_number(replace(split(split($h, ' von ')[1] || '', ' ')[0], '.', '')), listings: steps.search.listings}"},"params":{"additionalProperties":false,"properties":{"location":{"description":"City or district, e.g. 'Berlin', 'München', 'Hamburg-Altona'. The first match is used and returned as output.location. Omit to search all of Germany.","maxLength":80,"type":"string"},"max_price":{"description":"Maximum price in EUR","minimum":0,"type":"integer"},"min_price":{"description":"Minimum price in EUR","minimum":0,"type":"integer"},"page":{"default":1,"description":"Result page, 25 listings per page","maximum":50,"minimum":1,"type":"integer"},"query":{"description":"What to search for, e.g. 'fahrrad', 'ikea sofa'","maxLength":100,"minLength":1,"type":"string"},"radius_km":{"description":"Search radius around location in km. Only used together with location.","enum":[5,10,20,30,50,100,150,200],"type":"integer"},"sort":{"description":"'preis' = cheapest first. Omit for the site's default relevance order.","enum":["preis"],"type":"string"}},"required":["query"],"type":"object"},"provenance":{"method":"browser-inspect","notes":"spikes/kleinanzeigen.md. No JSON search API: the SRP (Astro microfrontend) embeds the result list in astro-island props (resultAds). Uses the canonical path, not /s-suchanfrage.html, because that form 302-redirects and Chrome hides redirect targets from fetch(redirect:'manual'). Verified path forms: empty sortierung:/preis::/k0l/r segments fall back to defaults; keyword may be percent-encoded. sortierung:preis = PRICE_AMOUNT (cheapest first); other sort tokens (neueste) are ignored by the site. Akamai is present but does not gate the SRP; credentials and custom headers are not needed.","recorded_at":"2026-11-07T11:45:00+01:00","recorded_by":"C4"},"requires_login":false,"schema":"https://wield.run/schema/recipe/v1.json","site":{"country":"DE","id":"kleinanzeigen.de","language":"de","login_url":"https://www.kleinanzeigen.de/m-einloggen.html","name":"Kleinanzeigen","origin":"https://www.kleinanzeigen.de","origins":["https://www.kleinanzeigen.de"]},"steps":[{"description":"Free-text place to Kleinanzeigen location id. Response is {\"_<id>\": \"<label>\"} with _0 = Deutschland first.","expect":{"assert":"length(keys(body)) > `1`","content_type":"json","status":[200]},"extract":{"json":{"id":"replace(items(@)[?[0] != '_0'] | [0][0], '_', '')","name":"items(@)[?[0] != '_0'] | [0][1]"}},"id":"location","request":{"headers":{"Accept":"application/json"},"method":"GET","query":{"query":"{{params.location}}"},"url":"/s-ort-empfehlungen.json"},"when":"params.location"},{"description":"Server-rendered result page. The result list is embedded as Astro island props (resultAds). On a zero-result page that island is missing, so the selector falls back to the sorting island, which yields an empty list instead of an error.","expect":{"content_type":"html","status":[200]},"extract":{"embedded_json":{"attr":"props","decode":"astro_props","selector":"astro-island[props*='resultAds'], html:not(:has(astro-island[props*='resultAds'])) astro-island[props*='selectedSortingField']","vars":{"listings":"resultAds[?organicAdPreview].organicAdPreview.{id: to_string(id), title: title, price_eur: to_number(replace(replace(replace(split(price || '', ' ')[0], '.', ''), ',', '.'), '€', '')), negotiable: contains(price || '', 'VB'), free: contains(price || '', 'verschenken'), price_text: price, zip: locationName, district: parentLocationName, posted_date: contains(sortingDate || '', '.') && join('-', reverse(split(sortingDate, '.'))) || `null`, posted_relative: starts_with(sortingDate || '', 'Heute') && 'today' || (starts_with(sortingDate || '', 'Gestern') && 'yesterday' || `null`), posted_time: contains(sortingDate || '', ',') && trim(split(sortingDate, ',')[1]) || `null`, seller_type: posterType && lower(posterType) || `null`, promoted: topAd == `true`, shipping: shippingAvailableValue != '' && shippingAvailableValue != `null`, url: join('', ['https://www.kleinanzeigen.de', seoLink]), image_url: imageList[0].xLargeUrl, description: description && replace(replace(replace(replace(replace(replace(description, '&quot;', '\"'), '&#39;', '\\''), '&#x27;', '\\''), '&#x2F;', '/'), '&lt;', '<'), '&amp;', '&') || `null`} || `[]`"}},"html":{"heading":{"selector":"h1"}}},"id":"search","parse":"html","request":{"headers":{"Accept":"text/html"},"method":"GET","url":"/s-sortierung:{{params.sort}}/preis:{{params.min_price}}:{{params.max_price}}/seite:{{params.page}}/{{params.query | urlencode}}/k0l{{steps.location.id}}r{{params.radius_km}}"}}],"task":"Search classified listings by keyword, location and price range","tos":{"notes":"Kleinanzeigen's terms forbid automated mass retrieval of listing data. This recipe runs one user-initiated search at a time in the user's own browser, at human pace. Do not loop over pages in bulk or store listings. Seller contact goes through the separate message-seller recipe, which needs the user's login and explicit Allow.","reviewed":false},"verify":{"checks":["length(output.listings) > `0`","output.location == 'Berlin'","output.total > `0`","length(output.listings[?price_eur != `null` && (price_eur < `50` || price_eur > `300`) && !promoted]) == `0`","starts_with(output.listings[0].url || '', 'https://www.kleinanzeigen.de/s-anzeige/')"],"example_params":{"location":"Berlin","max_price":300,"min_price":50,"query":"fahrrad"},"max_ms":6000},"version":1}