AutoScout24 Price Market — True Population Price Quantiles avatar

AutoScout24 Price Market — True Population Price Quantiles

Pricing

from $20.00 / 1,000 model market summaries

Go to Apify Store
AutoScout24 Price Market — True Population Price Quantiles

AutoScout24 Price Market — True Population Price Quantiles

Population price statistics for any car make/model on AutoScout24 in one call: the exact stock count and the true p10/p25/median/p75/p90 of the whole listing population, read from the site's own exact hit counts at price ceilings. Listing dumps stop at 200 pages and cannot reach these numbers.

Pricing

from $20.00 / 1,000 model market summaries

Rating

0.0

(0)

Developer

h ichi

h ichi

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

What is the median asking price of a BMW 3 Series in Germany? There are 11,013 of them listed on AutoScout24 right now. No listing scraper on this Store can answer that question — and the reason is not effort, it is arithmetic.

AutoScout24 stops paginating at 200 pages. Measured 2026-08-02: numberOfPages returns 200 for a 4,981-car result set, 200 for an 11,013-car result set, and 200 for the 62,236-car BMW population. At ~20 cars a page that is a hard ceiling of about 4,000 listings. A dump-style Actor cannot reach the middle of an 11,013-car market in principle, however many pages it pays for — and the 13 AutoScout24 scrapers already on the Store are all dump-style.

priceto=X is a different door. It is a search filter, and the site reports the exact hit count for any filter, so priceto=8600 answers "2,352 cars cost €8,600 or less" — a population CDF, exactly. Twelve of those requests give the real p10 / p25 / median / p75 / p90 with zero sampling error, in about 40 seconds.

That is what this Actor sells: one compact market record per make/model, with

  • price — p10 / p25 / median / p75 / p90 of the whole listing population, read out of the site's own exact counts and interpolated inside population bands. Never a page sample. In EUR and USD
  • totalFound — the exact live stock count, and pageCapReached telling you whether this is a market a listing dump could have reached at all
  • ladder and bands — the raw CDF, so you can rebuild any quantile or histogram yourself
  • sampleStats — dealer vs private split, median mileage, median registration year, fuel and gearbox mix, drawn newest-first (an ordering independent of price)
  • Optionally every sampled listing (price, mileage, first registration, fuel, gearbox, power, dealer or private)

Eight country front-ends: Germany, Austria, France, Italy, Spain, Netherlands, Belgium and the English-language international site. No login, no API key, no proxy, nothing stored between runs.

Pricing — from $0.02 per make/model, no subscription

EventPriceWhen
Make/model market summary$0.02Per make/model analyzed
Individual listing$0.002Only if you enable Include individual listings

A default run (1 model, summary only) costs $0.02 and makes 14 requests in about 40 seconds — roughly 2.4 MB on the wire, since every AutoScout24 page is ~170 KB gzipped (~720 KB decompressed). Two models fit comfortably in one call; beyond that the run's time budget starts trimming the ladder and says so in the record. A make/model that returns nothing is never charged.

Input

FieldExampleNotes
models["bmw/3er"]make or make/model slugs, or a full AutoScout24 search URL. Each costs $0.02
country"de"de, at, fr, it, es, nl, be, com. Sets the market, the domain and the currency
ladderSteps9Price ceilings to get exact counts for. One request each
refineSteps3Extra requests spent bisecting whichever band a quantile is stuck in, widest first
mileageMax100000Optional. Conditions the whole analysis on cars at or below this mileage
firstRegistrationFrom2018Optional. Conditions the whole analysis on cars first registered from this year
maxListings20Listings kept for the mix sample. Does not affect the price quantiles
includeIndividualItemsfalseAlso emit each sampled listing
convertToUsdtrueAdds USD stats at the current exchange rate

mileageMax and firstRegistrationFrom condition the entire record — the stock count, the ladder and the quantiles all become "given this filter". {"models": ["bmw/3er"], "mileageMax": 100000, "firstRegistrationFrom": 2018} is the price distribution of a 2018-or-newer 3 Series under 100,000 km: the shape a trade-in quote or a residual-value model actually needs, and one no listing dump can produce.

Model slugs are localisedbmw/3er on de/at, bmw/serie-3 on fr, bmw/3-series on it/es/nl/be/com. You do not have to know which: AutoScout24 308-redirects to its own slug and the Actor follows it while re-attaching your filters, which the redirect itself strips. resolvedName on the record tells you what the site decided you meant ("BMW Série 3" when bmw/3er is sent to France).

The one thing to understand: counts are exact, the mix is a sample

Every block carries its own basis and the record never lets the two blur:

BlockbasisWhy
price, ladder, bands, totalFoundcount-ladderEach rung is a filter, and AutoScout24 prints the exact hit count for whatever filter you send. priceto=17500 returning 4,410 means 4,410 cars cost €17,500 or less, full stop. The quantiles are exact at every band edge and linearly interpolated inside the band they land in
sampleStatssampleDealer share, mileage and age come from the ~20 listings actually fetched, with n stated. They are drawn sort=age&desc=1 — newest first — because that ordering is independent of price. A price-sorted page would tell you what the cheap end of the market looks like, which is a different question

If the ladder ever comes back non-monotonic, or flat (the signature of a filter the site did not apply), the Actor does not publish it as a population figure: it falls back to statistics over the listings it fetched, flips priceBasis to "sample", and adds a caveat saying so. You never have to guess which kind of number you are holding.

Output example (type: "market_summary", real measured output)

BMW 3er on autoscout24.de, 2026-08-02, 14 requests, 40 seconds:

{
"type": "market_summary",
"model": "bmw/3er",
"make": "bmw",
"modelSlug": "3er",
"country": "de",
"countryName": "Germany",
"currency": "EUR",
"totalFound": 11013,
"numberOfPages": 200,
"pageCapReached": true,
"resolvedCategory": "ma13gr100038",
"resolvedName": "BMW 3er",
"price": {
"p10": 4584, "p25": 10182, "median": 23030, "p75": 35857, "p90": 46228,
"min": 1, "max": 1000000, "count": 11013
},
"priceBasis": "count-ladder",
"ladder": [
{ "priceTo": 500, "cumulativeCount": 6, "cumulativeShare": 0.0005 },
{ "priceTo": 950, "cumulativeCount": 51, "cumulativeShare": 0.0046 },
{ "priceTo": 1800, "cumulativeCount": 221, "cumulativeShare": 0.0201 },
{ "priceTo": 3500, "cumulativeCount": 786, "cumulativeShare": 0.0714 },
{ "priceTo": 4800, "cumulativeCount": 1164, "cumulativeShare": 0.1057 },
{ "priceTo": 6700, "cumulativeCount": 1761, "cumulativeShare": 0.1599 },
{ "priceTo": 12500, "cumulativeCount": 3414, "cumulativeShare": 0.3100 },
{ "priceTo": 17500, "cumulativeCount": 4410, "cumulativeShare": 0.4004 },
{ "priceTo": 24500, "cumulativeCount": 5798, "cumulativeShare": 0.5265 },
{ "priceTo": 34000, "cumulativeCount": 7964, "cumulativeShare": 0.7231 },
{ "priceTo": 46500, "cumulativeCount": 9955, "cumulativeShare": 0.9039 },
{ "priceTo": 88500, "cumulativeCount": 10997, "cumulativeShare": 0.9985 }
],
"bands": [
{ "from": null, "to": 500, "count": 6 },
{ "from": 500, "to": 950, "count": 45 },
{ "from": 950, "to": 1800, "count": 170 },
{ "from": 1800, "to": 3500, "count": 565 },
{ "from": 3500, "to": 4800, "count": 378 },
{ "from": 4800, "to": 6700, "count": 597 },
{ "from": 6700, "to": 12500, "count": 1653 },
{ "from": 12500, "to": 17500, "count": 996 },
{ "from": 17500, "to": 24500, "count": 1388 },
{ "from": 24500, "to": 34000, "count": 2166 },
{ "from": 34000, "to": 46500, "count": 1991 },
{ "from": 46500, "to": 88500, "count": 1042 },
{ "from": 88500, "to": null, "count": 16 }
],
"sampleStats": {
"basis": "sample",
"sampleDesign": "newest-listings-first (sort=age), price-independent",
"n": 17,
"dealerCount": 8, "privateSellerCount": 9,
"dealerShare": 0.4706, "privateShare": 0.5294,
"medianMileageKm": 190000,
"medianFirstRegistrationYear": 2011,
"medianAgeYears": 15,
"medianPrice": 11900,
"fuelTop": [["Diesel", 10], ["Benzin", 7]],
"transmissionTop": [["Schaltgetriebe", 9], ["Automatik", 8]],
"excludedNonOrganic": 3
},
"ocsResultsReported": 212,
"filters": {
"mileageMaxKm": null, "firstRegistrationFrom": null,
"damagedListings": "excluded", "vehicleState": "new+used"
},
"requestsMade": 14,
"priceUsd": { "p10": 5277, "p25": 11721, "median": 26511, "p75": 41277, "p90": 53215 },
"exchangeRateEurUsd": 1.15115,
"sourceUrl": "https://www.autoscout24.de/lst/bmw/3er?atype=C&cy=D&damaged_listing=exclude&desc=0&powertype=kw&sort=price&ustate=N%2CU",
"checkedAt": "2026-08-02T15:42:01Z"
}

Read the ladder and the size of the problem becomes obvious. Half the German 3 Series market is under €24,500 — but 5,798 cars sit below that line, and the page cap can only ever show you about 4,000. The median is on the far side of a wall that paging cannot climb. The same call against France returns 1,371 cars and a €26,523 median: the same car, a market 8× smaller and 15% dearer.

What this Actor does not do

  • No personal data, ever. AutoScout24's listing JSON does carry seller.contactName (a named individual), seller.phones[] and location.street — for private sellers too. Those fields are dropped at the parser, not filtered at the end, and a guard asserts no emitted record contains them. A dealer keeps its company name; a private seller keeps nothing beyond the country its car is in. This is a market-structure tool, not a lead scraper — which is exactly where the existing AutoScout24 Actors, several of which advertise "Dealer Data" and "Phone Numbers", are pointed
  • No /lst?. AutoScout24's robots.txt disallows the make-less all-inventory search, so a make is always required and there is no free-text keyword mode. It also disallows both GraphQL endpoints and the lightweight count-only API, so this Actor pays for a full HTML page per count rather than take the cheap route it is not allowed to take
  • No detail-page fetching. /angebote/ is disallowed. Listing URLs are emitted so you can open them; they are never requested
  • No cat= in any URL (Disallow: /*?*cat=*). The site resolves the category itself and echoes it back, which is where resolvedCategory comes from
  • No browser, no proxy, no stored dataset. Plain HTTP, 256 MB, every run fetches live

Notes on the data

  • Asking prices, not transaction prices. Used cars turn over slowly and get repriced often; treat these as the live ask distribution
  • min and max are outliers by construction. A measured BMW 3er is listed at €1 (flagged priceLabel: toolow-price) and another at €1,000,000. The ladder deliberately starts at €500 and its top rung is anchored near the 99.8th percentile rather than the maximum, so the quantiles are unaffected — but do not read min/max as market signal
  • Promoted slots are excluded from the sample. searchResultType: "Nfm" entries look exactly like plain hits — isOcs: false, Main section — and only that one field gives them away. excludedNonOrganic reports how many were dropped. The site's default sort=standard is tier-weighted too: a measured page was 20 dealers out of 20, which is why every request here sends an explicit sort
  • A page renders 17-20 listings, not 20. The count varies with how many placements the page carried, so n is always measured
  • No listing dates. AutoScout24's result pages carry no publication timestamp, so no turnover or days-on-market metric is possible. firstRegistration gives the fleet's age distribution instead
  • Run it without a proxy. Verified 2026-08-02 with the internal dc-ip-probe, using the filtered URL form (&priceto=…), not just the bare one: a plain Apify datacenter IP gets 200 with and without the datacenter proxy, at every price ceiling tested
  • Counts drift between runs. AutoScout24's inventory changes minute to minute; the same query measured 11,008 / 11,012 / 11,013 within an hour. The ladder is internally consistent because every rung of one run is fetched within ~30 seconds