← appaday

Two dollars a week of watching the classifieds

Every hour, quietly, something looks at every new Kleinanzeigen ad within twenty kilometres of here, works out what the item is actually worth, and puts the handful worth driving to on one page. It has seen 8,406 ads. It has spent, in total, $2.48.

That number is the entire design. It is easy to point a model at a firehose; the work is in not paying for the 90% that was never going to matter.

A page headed 'Deals um Dunningen', a spend meter reading $0.021 of $1.00 today, and listing cards each showing a score, price, market value, realistic sale price, margin, a suggested bid, and bullet-pointed risks
Forty in the last day. Each card carries what it is worth, what to bid, and what could be wrong with it.

The funnel, and where it is allowed to spend

Everything hangs off four gates, each one an order of magnitude more expensive than the one before, and each one only reached by what survived:

The dedupe also decides how hard to scrape: it keeps paging until a page is 90% ads it already knows. That makes the first run a full backfill and every run after it two or three pages. A typical hour looks like "150 seen, 110 new, 8 deep, 2 alerts, $0.03", and there is an hour in the log that reads "275 seen, 219 new, 0 deep, $0.0000" — two hundred and nineteen genuinely new ads, none of them worth a second look, and it cost nothing to find that out.

The model's price memory is confidently wrong

The first version asked the model what something was worth, and it answered from training data with total conviction. An iPhone 14 Pro Max 128 GB came back at around 500 €. Ended auctions clear about 350.

So valuations do not come from the model any more. They come from eBay, and the model is only allowed to reason against them:

The correction is not subtle. An iPhone 16 listed at 550 € went from "95 — buy, market 750" to "35 — skip" the moment eBay said the median was 549.

Two things that quietly poison a median

Comparables are only as good as the search, and two classes of result will own the median the second they get in:

Accessories. A search for a Switch OLED returns cases, bags and screen protectors at 10–20 €. That is how a 190 € console came back valued at 20 €. The query extraction also has to strip bundle words — Nintendo Switch OLED Weiß + Zubehör + Tasche has to search for the console, not the bag.

Broken units and toy models. defekt, Bastler, Modellauto 1:43. Each filter only disqualifies when the query is not itself about one of those things, so somebody genuinely selling a phone case is still priced against phone cases.

And eBay hides the only number that matters

Sold prices are behind a sign-in wall — both LH_Sold=1 and LH_Complete=1 bounce a signed-out browser to the login page. So there is a one-off ebay-login.mjs that opens the tool's own Chrome visibly and lets you log in by hand, once.

What I like about how that landed: signed out, it does not pretend. Asking prices run 15–25% above what things actually sell for, so the prompt is told to treat the median as an upper bound, and the card shows an amber eBay Angebote badge instead of a green eBay verkauft one. Active results are cached for 24 hours only, so the day you log in, they replace themselves.

It runs as an hourly scheduled task with a hidden window and a daily ceiling of one dollar, which it has never come close to. Today it has spent two cents. Top of the board right now is a carved wooden Fasnet mask at 250 € against a market of 450, a compressor at 79 € worth about 170, and a Rimowa cabin case at 320 € worth 550 — which is either a shopping list or an argument that the thing works. Probably both.